| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- #pragma once
- #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
- #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
- #ifndef __has_include
- #define __has_include(s) 0
- #endif
- #if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
- // GCC 4.4 provides <condition_variable>
- #include <condition_variable>
- #elif __has_include(<condition_variable>) && !ANDROID
- // 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
- #include "common/std_mutex.h"
- #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
|