diff --git a/mingw.condition_variable.h b/mingw.condition_variable.h index 9db6e93..9862dc5 100644 --- a/mingw.condition_variable.h +++ b/mingw.condition_variable.h @@ -39,6 +39,10 @@ #include "mingw.mutex.h" #include "mingw.shared_mutex.h" +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) +#error To use the MinGW-std-threads library, you will need to define the macro _WIN32_WINNT to be 0x0501 (Windows XP) or higher. +#endif + namespace mingw_stdthread { #if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS) @@ -280,7 +284,8 @@ class condition_variable bool wait_impl (unique_lock & lock, DWORD time) { - static_assert(std::is_same::value, + using mutex_handle_type = typename xp::mutex::native_handle_type; + static_assert(std::is_same::value, "Native Win32 condition variable requires std::mutex to \ use native Win32 critical section objects."); xp::mutex * pmutex = lock.release(); @@ -298,7 +303,13 @@ use native Win32 critical section objects."); before_wait(pmutex); BOOL success = SleepConditionVariableSRW( native_handle(), pmutex->native_handle(), - time, 0); + time, +// CONDITION_VARIABLE_LOCKMODE_SHARED has a value not specified by +// Microsoft's Dev Center, but is known to be (convertible to) a ULONG. To +// ensure that the value passed to this function is not equal to Microsoft's +// constant, we can either use a static_assert, or simply generate an +// appropriate value. + !CONDITION_VARIABLE_LOCKMODE_SHARED); after_wait(pmutex); return success; } @@ -414,10 +425,6 @@ class condition_variable_any // Some shared_mutex functionality is available even in Vista, but it's not // until Windows 7 that a full implementation is natively possible. The class // itself is defined, with missing features, at the Vista feature level. - static_assert(CONDITION_VARIABLE_LOCKMODE_SHARED != 0, "The flag \ -CONDITION_VARIABLE_LOCKMODE_SHARED is not defined as expected. The value for \ -exclusive mode is unknown (not specified by Microsoft Dev Center), but assumed \ -to be 0. There is a conflict with CONDITION_VARIABLE_LOCKMODE_SHARED."); bool wait_impl (unique_lock & lock, DWORD time) { native_shared_mutex * pmutex = lock.release(); diff --git a/mingw.mutex.h b/mingw.mutex.h index e9678a4..c2a3ba7 100644 --- a/mingw.mutex.h +++ b/mingw.mutex.h @@ -48,6 +48,10 @@ // Need for the implementation of invoke #include "mingw.thread.h" +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) +#error To use the MinGW-std-threads library, you will need to define the macro _WIN32_WINNT to be 0x0501 (Windows XP) or higher. +#endif + namespace mingw_stdthread { // The _NonRecursive class has mechanisms that do not play nice with direct @@ -161,6 +165,7 @@ class mutex mutex & operator= (const mutex&) = delete; void lock (void) { +// Note: Undefined behavior if called recursively. #if STDMUTEX_RECURSION_CHECKS DWORD self = mOwnerThread.checkOwnerBeforeLock(); #endif @@ -216,6 +221,9 @@ class mutex mutex & operator= (const mutex&) = delete; ~mutex() noexcept { +// Undefined behavior if the mutex is held (locked) by any thread. +// Undefined behavior if a thread terminates while holding ownership of the +// mutex. DeleteCriticalSection(&mHandle); } void lock (void) diff --git a/mingw.shared_mutex.h b/mingw.shared_mutex.h index b6e540d..2d99288 100644 --- a/mingw.shared_mutex.h +++ b/mingw.shared_mutex.h @@ -55,6 +55,10 @@ // Might be able to use native Slim Reader-Writer (SRW) locks. #ifdef _WIN32 #include + +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) +#error To use the MinGW-std-threads library, you will need to define the macro _WIN32_WINNT to be 0x0501 (Windows XP) or higher. +#endif #endif namespace mingw_stdthread diff --git a/mingw.thread.h b/mingw.thread.h index db39e08..2d01f28 100644 --- a/mingw.thread.h +++ b/mingw.thread.h @@ -50,6 +50,10 @@ #include #endif +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) +#error To use the MinGW-std-threads library, you will need to define the macro _WIN32_WINNT to be 0x0501 (Windows XP) or higher. +#endif + // Instead of INVALID_HANDLE_VALUE, _beginthreadex returns 0. namespace mingw_stdthread { @@ -220,7 +224,14 @@ class thread static unsigned int _hardware_concurrency_helper() noexcept { SYSTEM_INFO sysinfo; +// This is one of the few functions used by the library which has a nearly- +// equivalent function defined in earlier versions of Windows. Include the +// workaround, just as a reminder that it does exist. +#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) ::GetNativeSystemInfo(&sysinfo); +#else + ::GetSystemInfo(&sysinfo); +#endif return sysinfo.dwNumberOfProcessors; } public: @@ -259,6 +270,11 @@ class thread } bool joinable() const {return mHandle != kInvalidHandle;} + +// Note: Due to lack of synchronization, this function has a race condition +// if called concurrently, which leads to undefined behavior. The same applies +// to all other member functions of this class, but this one is mentioned +// explicitly. void join() { using namespace std;