| 
									
										
										
										
											2013-03-29 07:42:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef CONDITION_VARIABLE_H_
 | 
					
						
							|  |  |  | #define CONDITION_VARIABLE_H_
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GCC_VER(x,y,z)	((x) * 10000 + (y) * 100 + (z))
 | 
					
						
							|  |  |  | #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-29 07:53:45 -07:00
										 |  |  | #ifndef __has_include
 | 
					
						
							|  |  |  | #define __has_include(s) 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-29 22:29:33 -05:00
										 |  |  | #if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ 
 | 
					
						
							| 
									
										
										
										
											2013-03-29 07:42:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GCC 4.4 provides <condition_variable>
 | 
					
						
							|  |  |  | #include <condition_variable>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-18 22:52:05 -05:00
										 |  |  | #elif __has_include(<condition_variable>) && !ANDROID
 | 
					
						
							| 
									
										
										
										
											2013-03-29 07:42:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // clang and libc++ provide <condition_variable> on OSX. However, the version
 | 
					
						
							|  |  |  | // of libc++ bundled with OSX 10.7 and 10.8 is buggy: it uses _ as a variable.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // We work around this issue by undefining and redefining _.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef _
 | 
					
						
							|  |  |  | #include <condition_variable>
 | 
					
						
							|  |  |  | #define _(s) wxGetTranslation((s))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // partial std::condition_variable implementation for win32/pthread
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-29 07:55:56 -07:00
										 |  |  | #include "StdMutex.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-29 07:42:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
 | 
					
						
							|  |  |  | #define USE_RVALUE_REFERENCES
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32) && defined(_M_X64)
 | 
					
						
							|  |  |  | #define USE_CONDITION_VARIABLES
 | 
					
						
							|  |  |  | #elif defined(_WIN32)
 | 
					
						
							|  |  |  | #define USE_EVENTS
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class condition_variable | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
					
						
							|  |  |  | 	typedef CONDITION_VARIABLE native_type; | 
					
						
							|  |  |  | #elif defined(_WIN32)
 | 
					
						
							|  |  |  | 	typedef HANDLE native_type; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	typedef pthread_cond_t native_type; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef USE_EVENTS
 | 
					
						
							|  |  |  | 	typedef native_type native_handle_type; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	typedef native_type* native_handle_type; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	condition_variable() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
					
						
							|  |  |  | 		InitializeConditionVariable(&m_handle); | 
					
						
							|  |  |  | #elif defined(_WIN32)
 | 
					
						
							|  |  |  | 		m_handle = CreateEvent(NULL, false, false, NULL); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		pthread_cond_init(&m_handle, NULL); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	~condition_variable() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
 | 
					
						
							|  |  |  | 		CloseHandle(m_handle); | 
					
						
							|  |  |  | #elif !defined(_WIN32)
 | 
					
						
							|  |  |  | 		pthread_cond_destroy(&m_handle); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	condition_variable(const condition_variable&) /*= delete*/; | 
					
						
							|  |  |  | 	condition_variable& operator=(const condition_variable&) /*= delete*/; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void notify_one() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
					
						
							|  |  |  | 		WakeConditionVariable(&m_handle); | 
					
						
							|  |  |  | #elif defined(_WIN32)
 | 
					
						
							|  |  |  | 		SetEvent(m_handle); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		pthread_cond_signal(&m_handle); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void notify_all() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
 | 
					
						
							|  |  |  | 		WakeAllConditionVariable(&m_handle); | 
					
						
							|  |  |  | #elif defined(_WIN32)
 | 
					
						
							|  |  |  | 		// TODO: broken
 | 
					
						
							|  |  |  | 		SetEvent(m_handle); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		pthread_cond_broadcast(&m_handle); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void wait(unique_lock<mutex>& lock) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	#ifdef USE_SRWLOCKS
 | 
					
						
							|  |  |  | 		SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0); | 
					
						
							|  |  |  | 	#elif defined(USE_CONDITION_VARIABLES)
 | 
					
						
							|  |  |  | 		SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		// TODO: broken, the unlock and wait need to be atomic
 | 
					
						
							|  |  |  | 		lock.unlock(); | 
					
						
							|  |  |  | 		WaitForSingleObject(m_handle, INFINITE); | 
					
						
							|  |  |  | 		lock.lock(); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		pthread_cond_wait(&m_handle, lock.mutex()->native_handle()); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	template <class Predicate> | 
					
						
							|  |  |  | 	void wait(unique_lock<mutex>& lock, Predicate pred) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		while (!pred()) | 
					
						
							|  |  |  | 			wait(lock); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//template <class Clock, class Duration>
 | 
					
						
							|  |  |  | 	//cv_status wait_until(unique_lock<mutex>& lock,
 | 
					
						
							|  |  |  | 	//	const chrono::time_point<Clock, Duration>& abs_time);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//template <class Clock, class Duration, class Predicate>
 | 
					
						
							|  |  |  | 	//	bool wait_until(unique_lock<mutex>& lock,
 | 
					
						
							|  |  |  | 	//	const chrono::time_point<Clock, Duration>& abs_time,
 | 
					
						
							|  |  |  | 	//	Predicate pred);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//template <class Rep, class Period>
 | 
					
						
							|  |  |  | 	//cv_status wait_for(unique_lock<mutex>& lock,
 | 
					
						
							|  |  |  | 	//	const chrono::duration<Rep, Period>& rel_time);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//template <class Rep, class Period, class Predicate>
 | 
					
						
							|  |  |  | 	//	bool wait_for(unique_lock<mutex>& lock,
 | 
					
						
							|  |  |  | 	//	const chrono::duration<Rep, Period>& rel_time,
 | 
					
						
							|  |  |  | 	//	Predicate pred);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	native_handle_type native_handle() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #ifdef USE_EVENTS
 | 
					
						
							|  |  |  | 		return m_handle; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		return &m_handle; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | 	native_type m_handle; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 |