summaryrefslogtreecommitdiff
path: root/src/common/std_condition_variable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/std_condition_variable.h')
-rw-r--r--src/common/std_condition_variable.h170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/common/std_condition_variable.h b/src/common/std_condition_variable.h
new file mode 100644
index 000000000..cee7a9dcd
--- /dev/null
+++ b/src/common/std_condition_variable.h
@@ -0,0 +1,170 @@
1
2#ifndef CONDITION_VARIABLE_H_
3#define CONDITION_VARIABLE_H_
4
5#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
6#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
7
8#ifndef __has_include
9#define __has_include(s) 0
10#endif
11
12#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
13
14// GCC 4.4 provides <condition_variable>
15#include <condition_variable>
16
17#elif __has_include(<condition_variable>) && !ANDROID
18
19// clang and libc++ provide <condition_variable> on OSX. However, the version
20// of libc++ bundled with OSX 10.7 and 10.8 is buggy: it uses _ as a variable.
21//
22// We work around this issue by undefining and redefining _.
23
24#undef _
25#include <condition_variable>
26#define _(s) wxGetTranslation((s))
27
28#else
29
30// partial std::condition_variable implementation for win32/pthread
31
32#include "std_mutex.h"
33
34#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
35#define USE_RVALUE_REFERENCES
36#endif
37
38#if defined(_WIN32) && defined(_M_X64)
39#define USE_CONDITION_VARIABLES
40#elif defined(_WIN32)
41#define USE_EVENTS
42#endif
43
44namespace std
45{
46
47class condition_variable
48{
49#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
50 typedef CONDITION_VARIABLE native_type;
51#elif defined(_WIN32)
52 typedef HANDLE native_type;
53#else
54 typedef pthread_cond_t native_type;
55#endif
56
57public:
58
59#ifdef USE_EVENTS
60 typedef native_type native_handle_type;
61#else
62 typedef native_type* native_handle_type;
63#endif
64
65 condition_variable()
66 {
67#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
68 InitializeConditionVariable(&m_handle);
69#elif defined(_WIN32)
70 m_handle = CreateEvent(NULL, false, false, NULL);
71#else
72 pthread_cond_init(&m_handle, NULL);
73#endif
74 }
75
76 ~condition_variable()
77 {
78#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
79 CloseHandle(m_handle);
80#elif !defined(_WIN32)
81 pthread_cond_destroy(&m_handle);
82#endif
83 }
84
85 condition_variable(const condition_variable&) /*= delete*/;
86 condition_variable& operator=(const condition_variable&) /*= delete*/;
87
88 void notify_one()
89 {
90#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
91 WakeConditionVariable(&m_handle);
92#elif defined(_WIN32)
93 SetEvent(m_handle);
94#else
95 pthread_cond_signal(&m_handle);
96#endif
97 }
98
99 void notify_all()
100 {
101#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
102 WakeAllConditionVariable(&m_handle);
103#elif defined(_WIN32)
104 // TODO: broken
105 SetEvent(m_handle);
106#else
107 pthread_cond_broadcast(&m_handle);
108#endif
109 }
110
111 void wait(unique_lock<mutex>& lock)
112 {
113#ifdef _WIN32
114 #ifdef USE_SRWLOCKS
115 SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
116 #elif defined(USE_CONDITION_VARIABLES)
117 SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
118 #else
119 // TODO: broken, the unlock and wait need to be atomic
120 lock.unlock();
121 WaitForSingleObject(m_handle, INFINITE);
122 lock.lock();
123 #endif
124#else
125 pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
126#endif
127 }
128
129 template <class Predicate>
130 void wait(unique_lock<mutex>& lock, Predicate pred)
131 {
132 while (!pred())
133 wait(lock);
134 }
135
136 //template <class Clock, class Duration>
137 //cv_status wait_until(unique_lock<mutex>& lock,
138 // const chrono::time_point<Clock, Duration>& abs_time);
139
140 //template <class Clock, class Duration, class Predicate>
141 // bool wait_until(unique_lock<mutex>& lock,
142 // const chrono::time_point<Clock, Duration>& abs_time,
143 // Predicate pred);
144
145 //template <class Rep, class Period>
146 //cv_status wait_for(unique_lock<mutex>& lock,
147 // const chrono::duration<Rep, Period>& rel_time);
148
149 //template <class Rep, class Period, class Predicate>
150 // bool wait_for(unique_lock<mutex>& lock,
151 // const chrono::duration<Rep, Period>& rel_time,
152 // Predicate pred);
153
154 native_handle_type native_handle()
155 {
156#ifdef USE_EVENTS
157 return m_handle;
158#else
159 return &m_handle;
160#endif
161 }
162
163private:
164 native_type m_handle;
165};
166
167}
168
169#endif
170#endif