mingw.condition_variable.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /**
  2. * @file condition_variable.h
  3. * @brief std::condition_variable implementation for MinGW
  4. *
  5. * (c) 2013-2016 by Mega Limited, Auckland, New Zealand
  6. * @author Alexander Vassilev
  7. *
  8. * @copyright Simplified (2-clause) BSD License.
  9. * You should have received a copy of the license along with this
  10. * program.
  11. *
  12. * This code is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * @note
  16. * This file may become part of the mingw-w64 runtime package. If/when this happens,
  17. * the appropriate license will be added, i.e. this code will become dual-licensed,
  18. * and the current BSD 2-clause license will stay.
  19. */
  20. #ifndef MINGW_CONDITIONAL_VARIABLE_H
  21. #define MINGW_CONDITIONAL_VARIABLE_H
  22. #if !defined(__cplusplus) || (__cplusplus < 201103L)
  23. #error A C++11 compiler is required!
  24. #endif
  25. // Use the standard classes for std::, if available.
  26. #include <condition_variable>
  27. #include <cassert>
  28. #include <chrono>
  29. #include <exception>
  30. #include <system_error>
  31. #include <sdkddkver.h> // Detect Windows version.
  32. #if (WINVER < _WIN32_WINNT_VISTA)
  33. #include <atomic>
  34. #endif
  35. #if (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
  36. #pragma message "The Windows API that MinGW-w32 provides is not fully compatible\
  37. with Microsoft's API. We'll try to work around this, but we can make no\
  38. guarantees. This problem does not exist in MinGW-w64."
  39. #include <windows.h> // No further granularity can be expected.
  40. #else
  41. #if (WINVER < _WIN32_WINNT_VISTA)
  42. #include <windef.h>
  43. #include <winbase.h> // For CreateSemaphore
  44. #include <handleapi.h>
  45. #endif
  46. #include <synchapi.h>
  47. #endif
  48. #include "mingw.mutex.h"
  49. #include "mingw.shared_mutex.h"
  50. #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
  51. #error To use the MinGW-std-threads library, you will need to define the macro _WIN32_WINNT to be 0x0501 (Windows XP) or higher.
  52. #endif
  53. namespace mingw_stdthread
  54. {
  55. #if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS) && !defined(__clang__)
  56. enum class cv_status { no_timeout, timeout };
  57. #else
  58. using std::cv_status;
  59. #endif
  60. namespace xp
  61. {
  62. // Include the XP-compatible condition_variable classes only if actually
  63. // compiling for XP. The XP-compatible classes are slower than the newer
  64. // versions, and depend on features not compatible with Windows Phone 8.
  65. #if (WINVER < _WIN32_WINNT_VISTA)
  66. class condition_variable_any
  67. {
  68. recursive_mutex mMutex {};
  69. std::atomic<int> mNumWaiters {0};
  70. HANDLE mSemaphore;
  71. HANDLE mWakeEvent {};
  72. public:
  73. using native_handle_type = HANDLE;
  74. native_handle_type native_handle()
  75. {
  76. return mSemaphore;
  77. }
  78. condition_variable_any(const condition_variable_any&) = delete;
  79. condition_variable_any& operator=(const condition_variable_any&) = delete;
  80. condition_variable_any()
  81. : mSemaphore(CreateSemaphoreA(NULL, 0, 0xFFFF, NULL))
  82. {
  83. if (mSemaphore == NULL)
  84. __builtin_trap();
  85. mWakeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  86. if (mWakeEvent == NULL)
  87. {
  88. CloseHandle(mSemaphore);
  89. __builtin_trap();
  90. }
  91. }
  92. ~condition_variable_any()
  93. {
  94. CloseHandle(mWakeEvent);
  95. CloseHandle(mSemaphore);
  96. }
  97. private:
  98. template <class M>
  99. bool wait_impl(M& lock, DWORD timeout)
  100. {
  101. {
  102. lock_guard<recursive_mutex> guard(mMutex);
  103. mNumWaiters++;
  104. }
  105. lock.unlock();
  106. DWORD ret = WaitForSingleObject(mSemaphore, timeout);
  107. mNumWaiters--;
  108. SetEvent(mWakeEvent);
  109. lock.lock();
  110. if (ret == WAIT_OBJECT_0)
  111. return true;
  112. else if (ret == WAIT_TIMEOUT)
  113. return false;
  114. //2 possible cases:
  115. //1)The point in notify_all() where we determine the count to
  116. //increment the semaphore with has not been reached yet:
  117. //we just need to decrement mNumWaiters, but setting the event does not hurt
  118. //
  119. //2)Semaphore has just been released with mNumWaiters just before
  120. //we decremented it. This means that the semaphore count
  121. //after all waiters finish won't be 0 - because not all waiters
  122. //woke up by acquiring the semaphore - we woke up by a timeout.
  123. //The notify_all() must handle this gracefully
  124. //
  125. else
  126. {
  127. using namespace std;
  128. __builtin_trap();
  129. }
  130. }
  131. public:
  132. template <class M>
  133. void wait(M& lock)
  134. {
  135. wait_impl(lock, INFINITE);
  136. }
  137. template <class M, class Predicate>
  138. void wait(M& lock, Predicate pred)
  139. {
  140. while(!pred())
  141. {
  142. wait(lock);
  143. };
  144. }
  145. void notify_all() noexcept
  146. {
  147. lock_guard<recursive_mutex> lock(mMutex); //block any further wait requests until all current waiters are unblocked
  148. if (mNumWaiters.load() <= 0)
  149. return;
  150. ReleaseSemaphore(mSemaphore, mNumWaiters, NULL);
  151. while(mNumWaiters > 0)
  152. {
  153. auto ret = WaitForSingleObject(mWakeEvent, 1000);
  154. if (ret == WAIT_FAILED || ret == WAIT_ABANDONED)
  155. std::terminate();
  156. }
  157. assert(mNumWaiters == 0);
  158. //in case some of the waiters timed out just after we released the
  159. //semaphore by mNumWaiters, it won't be zero now, because not all waiters
  160. //woke up by acquiring the semaphore. So we must zero the semaphore before
  161. //we accept waiters for the next event
  162. //See _wait_impl for details
  163. while(WaitForSingleObject(mSemaphore, 0) == WAIT_OBJECT_0);
  164. }
  165. void notify_one() noexcept
  166. {
  167. lock_guard<recursive_mutex> lock(mMutex);
  168. int targetWaiters = mNumWaiters.load() - 1;
  169. if (targetWaiters <= -1)
  170. return;
  171. ReleaseSemaphore(mSemaphore, 1, NULL);
  172. while(mNumWaiters > targetWaiters)
  173. {
  174. auto ret = WaitForSingleObject(mWakeEvent, 1000);
  175. if (ret == WAIT_FAILED || ret == WAIT_ABANDONED)
  176. std::terminate();
  177. }
  178. assert(mNumWaiters == targetWaiters);
  179. }
  180. template <class M, class Rep, class Period>
  181. cv_status wait_for(M& lock,
  182. const std::chrono::duration<Rep, Period>& rel_time)
  183. {
  184. using namespace std::chrono;
  185. auto timeout = duration_cast<milliseconds>(rel_time).count();
  186. DWORD waittime = (timeout < INFINITE) ? ((timeout < 0) ? 0 : static_cast<DWORD>(timeout)) : (INFINITE - 1);
  187. bool ret = wait_impl(lock, waittime) || (timeout >= INFINITE);
  188. return ret?cv_status::no_timeout:cv_status::timeout;
  189. }
  190. template <class M, class Rep, class Period, class Predicate>
  191. bool wait_for(M& lock,
  192. const std::chrono::duration<Rep, Period>& rel_time, Predicate pred)
  193. {
  194. return wait_until(lock, std::chrono::steady_clock::now()+rel_time, pred);
  195. }
  196. template <class M, class Clock, class Duration>
  197. cv_status wait_until (M& lock,
  198. const std::chrono::time_point<Clock,Duration>& abs_time)
  199. {
  200. return wait_for(lock, abs_time - Clock::now());
  201. }
  202. template <class M, class Clock, class Duration, class Predicate>
  203. bool wait_until (M& lock,
  204. const std::chrono::time_point<Clock, Duration>& abs_time,
  205. Predicate pred)
  206. {
  207. while (!pred())
  208. {
  209. if (wait_until(lock, abs_time) == cv_status::timeout)
  210. {
  211. return pred();
  212. }
  213. }
  214. return true;
  215. }
  216. };
  217. class condition_variable: condition_variable_any
  218. {
  219. using base = condition_variable_any;
  220. public:
  221. using base::native_handle_type;
  222. using base::native_handle;
  223. using base::base;
  224. using base::notify_all;
  225. using base::notify_one;
  226. void wait(unique_lock<mutex> &lock)
  227. {
  228. base::wait(lock);
  229. }
  230. template <class Predicate>
  231. void wait(unique_lock<mutex>& lock, Predicate pred)
  232. {
  233. base::wait(lock, pred);
  234. }
  235. template <class Rep, class Period>
  236. cv_status wait_for(unique_lock<mutex>& lock, const std::chrono::duration<Rep, Period>& rel_time)
  237. {
  238. return base::wait_for(lock, rel_time);
  239. }
  240. template <class Rep, class Period, class Predicate>
  241. bool wait_for(unique_lock<mutex>& lock, const std::chrono::duration<Rep, Period>& rel_time, Predicate pred)
  242. {
  243. return base::wait_for(lock, rel_time, pred);
  244. }
  245. template <class Clock, class Duration>
  246. cv_status wait_until (unique_lock<mutex>& lock, const std::chrono::time_point<Clock,Duration>& abs_time)
  247. {
  248. return base::wait_until(lock, abs_time);
  249. }
  250. template <class Clock, class Duration, class Predicate>
  251. bool wait_until (unique_lock<mutex>& lock, const std::chrono::time_point<Clock, Duration>& abs_time, Predicate pred)
  252. {
  253. return base::wait_until(lock, abs_time, pred);
  254. }
  255. };
  256. #endif // Compiling for XP
  257. } // Namespace mingw_stdthread::xp
  258. #if (WINVER >= _WIN32_WINNT_VISTA)
  259. namespace vista
  260. {
  261. // If compiling for Vista or higher, use the native condition variable.
  262. class condition_variable
  263. {
  264. static constexpr DWORD kInfinite = 0xffffffffl;
  265. #pragma GCC diagnostic push
  266. #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
  267. CONDITION_VARIABLE cvariable_ = CONDITION_VARIABLE_INIT;
  268. #pragma GCC diagnostic pop
  269. friend class condition_variable_any;
  270. #if STDMUTEX_RECURSION_CHECKS
  271. template<typename MTX>
  272. inline static void before_wait (MTX * pmutex)
  273. {
  274. pmutex->mOwnerThread.checkSetOwnerBeforeUnlock();
  275. }
  276. template<typename MTX>
  277. inline static void after_wait (MTX * pmutex)
  278. {
  279. pmutex->mOwnerThread.setOwnerAfterLock(GetCurrentThreadId());
  280. }
  281. #else
  282. inline static void before_wait (void *) { }
  283. inline static void after_wait (void *) { }
  284. #endif
  285. bool wait_impl (unique_lock<xp::mutex> & lock, DWORD time)
  286. {
  287. using mutex_handle_type = typename xp::mutex::native_handle_type;
  288. static_assert(std::is_same<mutex_handle_type, PCRITICAL_SECTION>::value,
  289. "Native Win32 condition variable requires std::mutex to \
  290. use native Win32 critical section objects.");
  291. xp::mutex * pmutex = lock.release();
  292. before_wait(pmutex);
  293. BOOL success = SleepConditionVariableCS(&cvariable_,
  294. pmutex->native_handle(),
  295. time);
  296. after_wait(pmutex);
  297. lock = unique_lock<xp::mutex>(*pmutex, adopt_lock);
  298. return success;
  299. }
  300. bool wait_unique (windows7::mutex * pmutex, DWORD time)
  301. {
  302. before_wait(pmutex);
  303. BOOL success = SleepConditionVariableSRW( native_handle(),
  304. pmutex->native_handle(),
  305. time,
  306. // CONDITION_VARIABLE_LOCKMODE_SHARED has a value not specified by
  307. // Microsoft's Dev Center, but is known to be (convertible to) a ULONG. To
  308. // ensure that the value passed to this function is not equal to Microsoft's
  309. // constant, we can either use a static_assert, or simply generate an
  310. // appropriate value.
  311. !CONDITION_VARIABLE_LOCKMODE_SHARED);
  312. after_wait(pmutex);
  313. return success;
  314. }
  315. bool wait_impl (unique_lock<windows7::mutex> & lock, DWORD time)
  316. {
  317. windows7::mutex * pmutex = lock.release();
  318. bool success = wait_unique(pmutex, time);
  319. lock = unique_lock<windows7::mutex>(*pmutex, adopt_lock);
  320. return success;
  321. }
  322. public:
  323. using native_handle_type = PCONDITION_VARIABLE;
  324. native_handle_type native_handle (void)
  325. {
  326. return &cvariable_;
  327. }
  328. condition_variable (void) = default;
  329. ~condition_variable (void) = default;
  330. condition_variable (const condition_variable &) = delete;
  331. condition_variable & operator= (const condition_variable &) = delete;
  332. void notify_one (void) noexcept
  333. {
  334. WakeConditionVariable(&cvariable_);
  335. }
  336. void notify_all (void) noexcept
  337. {
  338. WakeAllConditionVariable(&cvariable_);
  339. }
  340. void wait (unique_lock<mutex> & lock)
  341. {
  342. wait_impl(lock, kInfinite);
  343. }
  344. template<class Predicate>
  345. void wait (unique_lock<mutex> & lock, Predicate pred)
  346. {
  347. while (!pred())
  348. wait(lock);
  349. }
  350. template <class Rep, class Period>
  351. cv_status wait_for(unique_lock<mutex>& lock,
  352. const std::chrono::duration<Rep, Period>& rel_time)
  353. {
  354. using namespace std::chrono;
  355. auto timeout = duration_cast<milliseconds>(rel_time).count();
  356. DWORD waittime = (timeout < kInfinite) ? ((timeout < 0) ? 0 : static_cast<DWORD>(timeout)) : (kInfinite - 1);
  357. bool result = wait_impl(lock, waittime) || (timeout >= kInfinite);
  358. return result ? cv_status::no_timeout : cv_status::timeout;
  359. }
  360. template <class Rep, class Period, class Predicate>
  361. bool wait_for(unique_lock<mutex>& lock,
  362. const std::chrono::duration<Rep, Period>& rel_time,
  363. Predicate pred)
  364. {
  365. return wait_until(lock,
  366. std::chrono::steady_clock::now() + rel_time,
  367. std::move(pred));
  368. }
  369. template <class Clock, class Duration>
  370. cv_status wait_until (unique_lock<mutex>& lock,
  371. const std::chrono::time_point<Clock,Duration>& abs_time)
  372. {
  373. return wait_for(lock, abs_time - Clock::now());
  374. }
  375. template <class Clock, class Duration, class Predicate>
  376. bool wait_until (unique_lock<mutex>& lock,
  377. const std::chrono::time_point<Clock, Duration>& abs_time,
  378. Predicate pred)
  379. {
  380. while (!pred())
  381. {
  382. if (wait_until(lock, abs_time) == cv_status::timeout)
  383. {
  384. return pred();
  385. }
  386. }
  387. return true;
  388. }
  389. };
  390. class condition_variable_any
  391. {
  392. static constexpr DWORD kInfinite = 0xffffffffl;
  393. using native_shared_mutex = windows7::shared_mutex;
  394. condition_variable internal_cv_ {};
  395. // When available, the SRW-based mutexes should be faster than the
  396. // CriticalSection-based mutexes. Only try_lock will be unavailable in Vista,
  397. // and try_lock is not used by condition_variable_any.
  398. windows7::mutex internal_mutex_ {};
  399. template<class L>
  400. bool wait_impl (L & lock, DWORD time)
  401. {
  402. unique_lock<decltype(internal_mutex_)> internal_lock(internal_mutex_);
  403. lock.unlock();
  404. bool success = internal_cv_.wait_impl(internal_lock, time);
  405. lock.lock();
  406. return success;
  407. }
  408. // If the lock happens to be called on a native Windows mutex, skip any extra
  409. // contention.
  410. inline bool wait_impl (unique_lock<mutex> & lock, DWORD time)
  411. {
  412. return internal_cv_.wait_impl(lock, time);
  413. }
  414. // Some shared_mutex functionality is available even in Vista, but it's not
  415. // until Windows 7 that a full implementation is natively possible. The class
  416. // itself is defined, with missing features, at the Vista feature level.
  417. bool wait_impl (unique_lock<native_shared_mutex> & lock, DWORD time)
  418. {
  419. native_shared_mutex * pmutex = lock.release();
  420. bool success = internal_cv_.wait_unique(pmutex, time);
  421. lock = unique_lock<native_shared_mutex>(*pmutex, adopt_lock);
  422. return success;
  423. }
  424. bool wait_impl (shared_lock<native_shared_mutex> & lock, DWORD time)
  425. {
  426. native_shared_mutex * pmutex = lock.release();
  427. BOOL success = SleepConditionVariableSRW(native_handle(),
  428. pmutex->native_handle(), time,
  429. CONDITION_VARIABLE_LOCKMODE_SHARED);
  430. lock = shared_lock<native_shared_mutex>(*pmutex, adopt_lock);
  431. return success;
  432. }
  433. public:
  434. using native_handle_type = typename condition_variable::native_handle_type;
  435. native_handle_type native_handle (void)
  436. {
  437. return internal_cv_.native_handle();
  438. }
  439. void notify_one (void) noexcept
  440. {
  441. internal_cv_.notify_one();
  442. }
  443. void notify_all (void) noexcept
  444. {
  445. internal_cv_.notify_all();
  446. }
  447. condition_variable_any (void) = default;
  448. ~condition_variable_any (void) = default;
  449. template<class L>
  450. void wait (L & lock)
  451. {
  452. wait_impl(lock, kInfinite);
  453. }
  454. template<class L, class Predicate>
  455. void wait (L & lock, Predicate pred)
  456. {
  457. while (!pred())
  458. wait(lock);
  459. }
  460. template <class L, class Rep, class Period>
  461. cv_status wait_for(L& lock, const std::chrono::duration<Rep,Period>& period)
  462. {
  463. using namespace std::chrono;
  464. auto timeout = duration_cast<milliseconds>(period).count();
  465. DWORD waittime = (timeout < kInfinite) ? ((timeout < 0) ? 0 : static_cast<DWORD>(timeout)) : (kInfinite - 1);
  466. bool result = wait_impl(lock, waittime) || (timeout >= kInfinite);
  467. return result ? cv_status::no_timeout : cv_status::timeout;
  468. }
  469. template <class L, class Rep, class Period, class Predicate>
  470. bool wait_for(L& lock, const std::chrono::duration<Rep, Period>& period,
  471. Predicate pred)
  472. {
  473. return wait_until(lock, std::chrono::steady_clock::now() + period,
  474. std::move(pred));
  475. }
  476. template <class L, class Clock, class Duration>
  477. cv_status wait_until (L& lock,
  478. const std::chrono::time_point<Clock,Duration>& abs_time)
  479. {
  480. return wait_for(lock, abs_time - Clock::now());
  481. }
  482. template <class L, class Clock, class Duration, class Predicate>
  483. bool wait_until (L& lock,
  484. const std::chrono::time_point<Clock, Duration>& abs_time,
  485. Predicate pred)
  486. {
  487. while (!pred())
  488. {
  489. if (wait_until(lock, abs_time) == cv_status::timeout)
  490. {
  491. return pred();
  492. }
  493. }
  494. return true;
  495. }
  496. };
  497. } // Namespace vista
  498. #endif
  499. #if WINVER < 0x0600
  500. using xp::condition_variable;
  501. using xp::condition_variable_any;
  502. #else
  503. using vista::condition_variable;
  504. using vista::condition_variable_any;
  505. #endif
  506. } // Namespace mingw_stdthread
  507. // Push objects into std, but only if they are not already there.
  508. namespace std
  509. {
  510. // Because of quirks of the compiler, the common "using namespace std;"
  511. // directive would flatten the namespaces and introduce ambiguity where there
  512. // was none. Direct specification (std::), however, would be unaffected.
  513. // Take the safe option, and include only in the presence of MinGW's win32
  514. // implementation.
  515. #if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS) && !defined(__clang__)
  516. using mingw_stdthread::cv_status;
  517. using mingw_stdthread::condition_variable;
  518. using mingw_stdthread::condition_variable_any;
  519. #elif !defined(MINGW_STDTHREAD_REDUNDANCY_WARNING) // Skip repetition
  520. #define MINGW_STDTHREAD_REDUNDANCY_WARNING
  521. #pragma message "This version of MinGW seems to include a win32 port of\
  522. pthreads, and probably already has C++11 std threading classes implemented,\
  523. based on pthreads. These classes, found in namespace std, are not overridden\
  524. by the mingw-std-thread library. If you would still like to use this\
  525. implementation (as it is more lightweight), use the classes provided in\
  526. namespace mingw_stdthread."
  527. #endif
  528. }
  529. #endif // MINGW_CONDITIONAL_VARIABLE_H