20#ifndef WIN32STDMUTEX_H
21#define WIN32STDMUTEX_H
23#if !defined(__cplusplus) || (__cplusplus < 201103L)
24#error A C++11 compiler is required!
30#if defined(STDMUTEX_NO_RECURSION_CHECKS) && !defined(NDEBUG)
31 #undef STDMUTEX_NO_RECURSION_CHECKS
36#include <system_error>
50 #define EOWNERDEAD 133
58#ifndef STDMUTEX_NO_RECURSION_CHECKS
61class condition_variable;
68using std::unique_lock;
69using std::adopt_lock_t;
70using std::defer_lock_t;
71using std::try_to_lock_t;
74using std::try_to_lock;
85 InitializeCriticalSection(&
mHandle);
91 DeleteCriticalSection(&
mHandle);
103 return (TryEnterCriticalSection(&
mHandle)!=0);
115 DWORD self = GetCurrentThreadId();
116 if (
mOwnerThread.load(std::memory_order_relaxed) == self)
118 std::fprintf(stderr,
"FATAL: Recursive locking of non-recursive mutex detected. Throwing system exception\n");
120 throw std::system_error(EDEADLK, std::generic_category());
130 DWORD self = GetCurrentThreadId();
131 if (
mOwnerThread.load(std::memory_order_relaxed) != self)
133 std::fprintf(stderr,
"FATAL: Recursive unlocking of non-recursive mutex detected. Throwing system exception\n");
135 throw std::system_error(EDEADLK, std::generic_category());
181#if defined(_WIN32) && (WINVER >= _WIN32_WINNT_VISTA)
188#ifndef STDMUTEX_NO_RECURSION_CHECKS
189 friend class vista::condition_variable;
190 _OwnerThread mOwnerThread;
193 typedef PSRWLOCK native_handle_type;
194 constexpr mutex () noexcept : mHandle(SRWLOCK_INIT)
195#ifndef STDMUTEX_NO_RECURSION_CHECKS
199 mutex (
const mutex&) =
delete;
200 mutex & operator= (
const mutex&) =
delete;
203#ifndef STDMUTEX_NO_RECURSION_CHECKS
204 DWORD self = mOwnerThread.checkOwnerBeforeLock();
206 AcquireSRWLockExclusive(&mHandle);
207#ifndef STDMUTEX_NO_RECURSION_CHECKS
208 mOwnerThread.setOwnerAfterLock(self);
213#ifndef STDMUTEX_NO_RECURSION_CHECKS
214 mOwnerThread.checkSetOwnerBeforeUnlock();
216 ReleaseSRWLockExclusive(&mHandle);
219#if (WINVER >= _WIN32_WINNT_WIN7)
222#ifndef STDMUTEX_NO_RECURSION_CHECKS
223 DWORD self = mOwnerThread.checkOwnerBeforeLock();
225 BOOL ret = TryAcquireSRWLockExclusive(&mHandle);
226#ifndef STDMUTEX_NO_RECURSION_CHECKS
228 mOwnerThread.setOwnerAfterLock(self);
233 native_handle_type native_handle (
void)
253#ifndef STDMUTEX_NO_RECURSION_CHECKS
260#ifndef STDMUTEX_NO_RECURSION_CHECKS
268 DeleteCriticalSection(&
mHandle);
272 unsigned char state =
mState.load(std::memory_order_acquire);
274 if ((state == 2) &&
mState.compare_exchange_weak(state, 1, std::memory_order_acquire))
276 InitializeCriticalSection(&
mHandle);
277 mState.store(0, std::memory_order_release);
283#ifndef STDMUTEX_NO_RECURSION_CHECKS
286 EnterCriticalSection(&
mHandle);
287#ifndef STDMUTEX_NO_RECURSION_CHECKS
293 assert(
mState.load(std::memory_order_relaxed) == 0);
294#ifndef STDMUTEX_NO_RECURSION_CHECKS
297 LeaveCriticalSection(&
mHandle);
301 unsigned char state =
mState.load(std::memory_order_acquire);
302 if ((state == 2) &&
mState.compare_exchange_strong(state, 1, std::memory_order_acquire))
304 InitializeCriticalSection(&
mHandle);
305 mState.store(0, std::memory_order_release);
309#ifndef STDMUTEX_NO_RECURSION_CHECKS
312 BOOL ret = TryEnterCriticalSection(&
mHandle);
313#ifndef STDMUTEX_NO_RECURSION_CHECKS
325#if (WINVER >= _WIN32_WINNT_WIN7)
326using windows7::mutex;
338#ifndef STDMUTEX_NO_RECURSION_CHECKS
348#ifndef STDMUTEX_NO_RECURSION_CHECKS
358 DWORD ret = WaitForSingleObject(
mHandle, INFINITE);
359 if (ret != WAIT_OBJECT_0)
361 if (ret == WAIT_ABANDONED)
362 throw std::system_error(
EOWNERDEAD, std::generic_category());
364 throw std::system_error(
EPROTO, std::generic_category());
370 throw std::system_error(EDEADLK, std::generic_category());
374 DWORD ret = WaitForSingleObject(
mHandle, 0);
375 if (ret == WAIT_TIMEOUT)
377 else if (ret == WAIT_OBJECT_0)
379 else if (ret == WAIT_ABANDONED)
380 throw std::system_error(
EOWNERDEAD, std::generic_category());
382 throw std::system_error(
EPROTO, std::generic_category());
384 template <
class Rep,
class Period>
387 DWORD timeout = (DWORD)std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
389 DWORD ret = WaitForSingleObject(
mHandle, timeout);
390 if (ret == WAIT_TIMEOUT)
392 else if (ret == WAIT_OBJECT_0)
394 else if (ret == WAIT_ABANDONED)
395 throw std::system_error(
EOWNERDEAD, std::generic_category());
397 throw std::system_error(
EPROTO, std::generic_category());
399 template <
class Clock,
class Duration>
407#ifndef STDMUTEX_NO_RECURSION_CHECKS
435 template <
class Rep,
class Period>
444 template <
class Clock,
class Duration>
455typedef recursive_timed_mutex timed_mutex;
464 template<
class Callable,
class... Args>
470template<
class Callable,
class... Args>
473 if (flag.
mHasRun.load(std::memory_order_acquire))
475 lock_guard<mutex> lock(flag.
mMutex);
476 if (flag.
mHasRun.load(std::memory_order_acquire))
478 detail::invoke(std::forward<Callable>(func),std::forward<Args>(args)...);
479 flag.
mHasRun.store(
true, std::memory_order_release);
491#if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS)
493using mingw_stdthread::mutex;
498#elif !defined(MINGW_STDTHREAD_REDUNDANCY_WARNING)
499#define MINGW_STDTHREAD_REDUNDANCY_WARNING
500#pragma message "This version of MinGW seems to include a win32 port of\
501 pthreads, and probably already has C++11 std threading classes implemented,\
502 based on pthreads. These classes, found in namespace std, are not overridden\
503 by the mingw-std-thread library. If you would still like to use this\
504 implementation (as it is more lightweight), use the classes provided in\
505 namespace mingw_stdthread."
friend void call_once(once_flag &once, Callable &&f, Args &&... args)
once_flag(const once_flag &)=delete
constexpr once_flag() noexcept
once_flag & operator=(const once_flag &)=delete
recursive_mutex & operator=(const recursive_mutex &)=delete
LPCRITICAL_SECTION native_handle_type
native_handle_type native_handle()
~recursive_mutex() noexcept
recursive_mutex() noexcept
recursive_mutex(const recursive_mutex &)=delete
recursive_timed_mutex & operator=(const recursive_timed_mutex &)=delete
HANDLE native_handle_type
recursive_timed_mutex(const recursive_timed_mutex &)=delete
native_handle_type native_handle() const
bool try_lock_for(const std::chrono::duration< Rep, Period > &dur)
bool try_lock_until(const std::chrono::time_point< Clock, Duration > &timeout_time)
_OwnerThread mOwnerThread
recursive_timed_mutex base
bool try_lock_for(const std::chrono::duration< Rep, Period > &dur)
timed_mutex(const timed_mutex &)=delete
bool try_lock_until(const std::chrono::time_point< Clock, Duration > &timeout_time)
timed_mutex & operator=(const timed_mutex &)=delete
native_handle_type native_handle(void)
mutex(const mutex &)=delete
mutex & operator=(const mutex &)=delete
_OwnerThread mOwnerThread
constexpr mutex() noexcept
PCRITICAL_SECTION native_handle_type
std::thread implementation for MinGW (c) 2013-2016 by Mega Limited, Auckland, New Zealand
auto invoke(F &&f, Args &&... args) -> decltype(InvokeResult< F, Args... >::invoke(std::forward< F >(f), std::forward< Args >(args)...))
void call_once(once_flag &flag, Callable &&func, Args &&... args)
Provides common mathematical functions and vector operations.
void checkSetOwnerBeforeUnlock()
void setOwnerAfterLock(DWORD id)
std::atomic< DWORD > mOwnerThread
constexpr _OwnerThread() noexcept
DWORD checkOwnerBeforeLock() const