std_condition_variable.h 4.1 KB

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