21#ifndef MINGW_CONDITIONAL_VARIABLE_H
22#define MINGW_CONDITIONAL_VARIABLE_H
24#if !defined(__cplusplus) || (__cplusplus < 201103L)
25#error A C++11 compiler is required!
28#include <condition_variable>
33#include <system_error>
40#if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS)
41enum class cv_status { no_timeout, timeout };
64 mSemaphore(CreateSemaphore(NULL, 0, 0xFFFF, NULL)),
65 mWakeEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
77 lock_guard<recursive_mutex> guard(
mMutex);
81 DWORD ret = WaitForSingleObject(
mSemaphore, timeout);
86 if (ret == WAIT_OBJECT_0)
88 else if (ret == WAIT_TIMEOUT)
102 throw std::system_error(
EPROTO, std::generic_category());
110 template <
class M,
class Predicate>
111 void wait(M& lock, Predicate pred)
121 lock_guard<recursive_mutex> lock(
mMutex);
128 auto ret = WaitForSingleObject(
mWakeEvent, 1000);
129 if (ret == WAIT_FAILED || ret == WAIT_ABANDONED)
138 while(WaitForSingleObject(
mSemaphore, 0) == WAIT_OBJECT_0);
142 lock_guard<recursive_mutex> lock(
mMutex);
144 if (targetWaiters <= -1)
149 auto ret = WaitForSingleObject(
mWakeEvent, 1000);
150 if (ret == WAIT_FAILED || ret == WAIT_ABANDONED)
155 template <
class M,
class Rep,
class Period>
157 const std::chrono::duration<Rep, Period>& rel_time)
159 using namespace std::chrono;
160 long long timeout = duration_cast<milliseconds>(rel_time).count();
163 bool ret =
wait_impl(lock, (DWORD)timeout);
164 return ret?cv_status::no_timeout:cv_status::timeout;
167 template <
class M,
class Rep,
class Period,
class Predicate>
169 const std::chrono::duration<Rep, Period>& rel_time, Predicate pred)
171 return wait_until(lock, std::chrono::steady_clock::now()+rel_time, pred);
173 template <
class M,
class Clock,
class Duration>
175 const std::chrono::time_point<Clock,Duration>& abs_time)
177 return wait_for(lock, abs_time - Clock::now());
179 template <
class M,
class Clock,
class Duration,
class Predicate>
181 const std::chrono::time_point<Clock, Duration>& abs_time,
186 if (
wait_until(lock, abs_time) == cv_status::timeout)
204 void wait(unique_lock<mutex> &lock)
208 template <
class Predicate>
209 void wait(unique_lock<mutex>& lock, Predicate pred)
213 template <
class Rep,
class Period>
214 cv_status
wait_for(unique_lock<mutex>& lock,
const std::chrono::duration<Rep, Period>& rel_time)
218 template <
class Rep,
class Period,
class Predicate>
219 bool wait_for(unique_lock<mutex>& lock,
const std::chrono::duration<Rep, Period>& rel_time, Predicate pred)
223 template <
class Clock,
class Duration>
224 cv_status
wait_until (unique_lock<mutex>& lock,
const std::chrono::time_point<Clock,Duration>& abs_time)
228 template <
class Clock,
class Duration,
class Predicate>
229 bool wait_until (unique_lock<mutex>& lock,
const std::chrono::time_point<Clock, Duration>& abs_time, Predicate pred)
236#if (WINVER >= _WIN32_WINNT_VISTA)
245#ifndef STDMUTEX_NO_RECURSION_CHECKS
246 template<
typename MTX>
249 pmutex->mOwnerThread.checkSetOwnerBeforeUnlock();
251 template<
typename MTX>
254 pmutex->mOwnerThread.setOwnerAfterLock(GetCurrentThreadId());
261 bool wait_impl (unique_lock<xp::mutex> & lock, DWORD time)
263 static_assert(std::is_same<typename xp::mutex::native_handle_type, PCRITICAL_SECTION>::value,
264 "Native Win32 condition variable requires std::mutex to \
265use native Win32 critical section objects.");
268 BOOL success = SleepConditionVariableCS(&
cvariable_,
272 lock = unique_lock<xp::mutex>(*pmutex, adopt_lock);
276 bool wait_impl (unique_lock<windows7::mutex> & lock, DWORD time)
278 windows7::mutex * pmutex = lock.release();
281 pmutex->native_handle(),
284 lock = unique_lock<windows7::mutex>(*pmutex, adopt_lock);
315 void wait (unique_lock<mutex> & lock)
320 template<
class Predicate>
321 void wait (unique_lock<mutex> & lock, Predicate pred)
327 template <
class Rep,
class Period>
329 const std::chrono::duration<Rep, Period>& rel_time)
331 using namespace std::chrono;
332 auto time = duration_cast<milliseconds>(rel_time).count();
335 bool result =
wait_impl(lock,
static_cast<DWORD
>(time));
336 return result ? cv_status::no_timeout : cv_status::timeout;
339 template <
class Rep,
class Period,
class Predicate>
341 const std::chrono::duration<Rep, Period>& rel_time,
345 std::chrono::steady_clock::now() + rel_time,
348 template <
class Clock,
class Duration>
350 const std::chrono::time_point<Clock,Duration>& abs_time)
352 return wait_for(lock, abs_time - Clock::now());
354 template <
class Clock,
class Duration,
class Predicate>
356 const std::chrono::time_point<Clock, Duration>& abs_time,
361 if (
wait_until(lock, abs_time) == cv_status::timeout)
389 inline bool wait_impl (unique_lock<mutex> & lock, DWORD time)
396 static_assert(CONDITION_VARIABLE_LOCKMODE_SHARED != 0,
"The flag \
397CONDITION_VARIABLE_LOCKMODE_SHARED is not defined as expected. The flag for \
398exclusive mode is unknown (not specified by Microsoft Dev Center), but assumed \
399to be 0. There is a conflict with CONDITION_VARIABLE_LOCKMODE_SHARED.");
401 bool wait_impl (unique_lock<native_shared_mutex> & lock, DWORD time)
405 pmutex->native_handle(), time, 0);
406 lock = unique_lock<native_shared_mutex>(*pmutex, adopt_lock);
413 pmutex->native_handle(), time,
414 CONDITION_VARIABLE_LOCKMODE_SHARED);
439 template<
class L,
class Predicate>
440 void wait (L & lock, Predicate pred)
446 template <
class L,
class Rep,
class Period>
447 cv_status
wait_for(L& lock,
const std::chrono::duration<Rep, Period>& period)
449 using namespace std::chrono;
450 auto time = duration_cast<milliseconds>(period).count();
453 bool result =
wait_impl(lock,
static_cast<DWORD
>(time));
454 return result ? cv_status::no_timeout : cv_status::timeout;
457 template <
class L,
class Rep,
class Period,
class Predicate>
458 bool wait_for(L& lock,
const std::chrono::duration<Rep, Period>& period,
461 return wait_until(lock, std::chrono::steady_clock::now() + period,
464 template <
class L,
class Clock,
class Duration>
466 const std::chrono::time_point<Clock,Duration>& abs_time)
468 return wait_for(lock, abs_time - Clock::now());
470 template <
class L,
class Clock,
class Duration,
class Predicate>
472 const std::chrono::time_point<Clock, Duration>& abs_time,
477 if (
wait_until(lock, abs_time) == cv_status::timeout)
488using xp::condition_variable;
489using xp::condition_variable_any;
491using vista::condition_variable;
492using vista::condition_variable_any;
504#if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS)
505using mingw_stdthread::cv_status;
508#elif !defined(MINGW_STDTHREAD_REDUNDANCY_WARNING)
509#define MINGW_STDTHREAD_REDUNDANCY_WARNING
510#pragma message "This version of MinGW seems to include a win32 port of\
511 pthreads, and probably already has C++11 std threading classes implemented,\
512 based on pthreads. These classes, found in namespace std, are not overridden\
513 by the mingw-std-thread library. If you would still like to use this\
514 implementation (as it is more lightweight), use the classes provided in\
515 namespace mingw_stdthread."
mutex_type * release(void) noexcept
condition_variable_any(void)
cv_status wait_until(L &lock, const std::chrono::time_point< Clock, Duration > &abs_time)
bool wait_until(L &lock, const std::chrono::time_point< Clock, Duration > &abs_time, Predicate pred)
bool wait_for(L &lock, const std::chrono::duration< Rep, Period > &period, Predicate pred)
windows7::shared_mutex native_shared_mutex
base::native_handle_type native_handle_type
bool wait_impl(unique_lock< mutex > &lock, DWORD time)
bool wait_impl(unique_lock< native_shared_mutex > &lock, DWORD time)
bool wait_impl(L &lock, DWORD time)
~condition_variable_any(void)=default
cv_status wait_for(L &lock, const std::chrono::duration< Rep, Period > &period)
bool wait_impl(shared_lock< native_shared_mutex > &lock, DWORD time)
void wait(L &lock, Predicate pred)
PCONDITION_VARIABLE native_handle_type
CONDITION_VARIABLE cvariable_
bool wait_impl(unique_lock< windows7::mutex > &lock, DWORD time)
native_handle_type native_handle(void)
void notify_one(void) noexcept
void wait(unique_lock< mutex > &lock)
void wait(unique_lock< mutex > &lock, Predicate pred)
~condition_variable(void)=default
condition_variable & operator=(const condition_variable &)=delete
cv_status wait_until(unique_lock< mutex > &lock, const std::chrono::time_point< Clock, Duration > &abs_time)
static void before_wait(MTX *pmutex)
bool wait_for(unique_lock< mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time, Predicate pred)
bool wait_impl(unique_lock< xp::mutex > &lock, DWORD time)
static void after_wait(MTX *pmutex)
cv_status wait_for(unique_lock< mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time)
void notify_all(void) noexcept
condition_variable(const condition_variable &)=delete
bool wait_until(unique_lock< mutex > &lock, const std::chrono::time_point< Clock, Duration > &abs_time, Predicate pred)
HANDLE native_handle_type
bool wait_for(M &lock, const std::chrono::duration< Rep, Period > &rel_time, Predicate pred)
bool wait_impl(M &lock, DWORD timeout)
~condition_variable_any()
condition_variable_any & operator=(const condition_variable_any &)=delete
void notify_one() noexcept
void wait(M &lock, Predicate pred)
cv_status wait_until(M &lock, const std::chrono::time_point< Clock, Duration > &abs_time)
native_handle_type native_handle()
bool wait_until(M &lock, const std::chrono::time_point< Clock, Duration > &abs_time, Predicate pred)
std::atomic< int > mNumWaiters
cv_status wait_for(M &lock, const std::chrono::duration< Rep, Period > &rel_time)
condition_variable_any(const condition_variable_any &)=delete
void notify_all() noexcept
bool wait_until(unique_lock< mutex > &lock, const std::chrono::time_point< Clock, Duration > &abs_time, Predicate pred)
cv_status wait_until(unique_lock< mutex > &lock, const std::chrono::time_point< Clock, Duration > &abs_time)
void wait(unique_lock< mutex > &lock, Predicate pred)
cv_status wait_for(unique_lock< mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time)
void wait(unique_lock< mutex > &lock)
bool wait_for(unique_lock< mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time, Predicate pred)
condition_variable_any base
native_handle_type native_handle(void)
std::mutex et al implementation for MinGW (c) 2013-2016 by Mega Limited, Auckland,...
Standard-compliant shared_mutex for MinGW.
Provides common mathematical functions and vector operations.