From 0a16e53b40d347db7dcd04cb694d0f8f2ed1a5a7 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 6 Oct 2016 21:13:04 +0200 Subject: [PATCH] Fix C++11 Windows build of threading code The initial problem was that mutex_auto_lock.h tries to use std::unique_lock despite mutex.h not using C++11's std::mutex on Windows. The problem here is the mismatch between C++11 usage conditions of the two headers. This commit moves the decision logic to threads.h and makes sure mutex.h, mutex_auto_lock.h and event.h all use the same features. --- src/threading/event.cpp | 16 ++++++++-------- src/threading/event.h | 17 ++++++----------- src/threading/mutex.cpp | 19 +++++++++---------- src/threading/mutex.h | 15 ++++++++------- src/threading/mutex_auto_lock.h | 4 +++- src/threading/thread.cpp | 20 ++++++++++---------- src/threading/thread.h | 13 ++++--------- src/threads.h | 18 +++++++++++++++++- 8 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/threading/event.cpp b/src/threading/event.cpp index 165f9d83f..0d5928f10 100644 --- a/src/threading/event.cpp +++ b/src/threading/event.cpp @@ -27,8 +27,8 @@ DEALINGS IN THE SOFTWARE. Event::Event() { -#if __cplusplus < 201103L -# ifdef _WIN32 +#ifndef USE_CPP11_MUTEX +# if USE_WIN_MUTEX event = CreateEvent(NULL, false, false, NULL); # else pthread_cond_init(&cv, NULL); @@ -38,10 +38,10 @@ Event::Event() #endif } -#if __cplusplus < 201103L +#ifndef USE_CPP11_MUTEX Event::~Event() { -#ifdef _WIN32 +#if USE_WIN_MUTEX CloseHandle(event); #else pthread_cond_destroy(&cv); @@ -53,13 +53,13 @@ Event::~Event() void Event::wait() { -#if __cplusplus >= 201103L +#if USE_CPP11_MUTEX MutexAutoLock lock(mutex); while (!notified) { cv.wait(lock); } notified = false; -#elif defined(_WIN32) +#elif USE_WIN_MUTEX WaitForSingleObject(event, INFINITE); #else pthread_mutex_lock(&mutex); @@ -74,11 +74,11 @@ void Event::wait() void Event::signal() { -#if __cplusplus >= 201103L +#if USE_CPP11_MUTEX MutexAutoLock lock(mutex); notified = true; cv.notify_one(); -#elif defined(_WIN32) +#elif USE_WIN_MUTEX SetEvent(event); #else pthread_mutex_lock(&mutex); diff --git a/src/threading/event.h b/src/threading/event.h index dd5164576..26cb8997a 100644 --- a/src/threading/event.h +++ b/src/threading/event.h @@ -26,17 +26,12 @@ DEALINGS IN THE SOFTWARE. #ifndef THREADING_EVENT_H #define THREADING_EVENT_H -#if __cplusplus >= 201103L +#include "threads.h" + +#if USE_CPP11_MUTEX #include #include "threading/mutex.h" #include "threading/mutex_auto_lock.h" -#elif defined(_WIN32) - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include -#else - #include #endif @@ -49,18 +44,18 @@ DEALINGS IN THE SOFTWARE. class Event { public: Event(); -#if __cplusplus < 201103L +#ifndef USE_CPP11_MUTEX ~Event(); #endif void wait(); void signal(); private: -#if __cplusplus >= 201103L +#if USE_CPP11_MUTEX std::condition_variable cv; Mutex mutex; bool notified; -#elif defined(_WIN32) +#elif USE_WIN_MUTEX HANDLE event; #else pthread_cond_t cv; diff --git a/src/threading/mutex.cpp b/src/threading/mutex.cpp index f2b07bec3..0908b5d37 100644 --- a/src/threading/mutex.cpp +++ b/src/threading/mutex.cpp @@ -23,14 +23,13 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// Windows std::mutex is much slower than the critical section API -#if __cplusplus < 201103L || defined(_WIN32) +#include "threads.h" + +#ifndef USE_CPP11_MUTEX #include "threading/mutex.h" -#ifndef _WIN32 - #include -#endif +#include #define UNUSED(expr) do { (void)(expr); } while (0) @@ -47,7 +46,7 @@ Mutex::Mutex(bool recursive) void Mutex::init_mutex(bool recursive) { -#ifdef _WIN32 +#if USE_WIN_MUTEX // Windows critical sections are recursive by default UNUSED(recursive); @@ -69,7 +68,7 @@ void Mutex::init_mutex(bool recursive) Mutex::~Mutex() { -#ifdef _WIN32 +#if USE_WIN_MUTEX DeleteCriticalSection(&mutex); #else int ret = pthread_mutex_destroy(&mutex); @@ -80,7 +79,7 @@ Mutex::~Mutex() void Mutex::lock() { -#ifdef _WIN32 +#if USE_WIN_MUTEX EnterCriticalSection(&mutex); #else int ret = pthread_mutex_lock(&mutex); @@ -91,7 +90,7 @@ void Mutex::lock() void Mutex::unlock() { -#ifdef _WIN32 +#if USE_WIN_MUTEX LeaveCriticalSection(&mutex); #else int ret = pthread_mutex_unlock(&mutex); @@ -104,5 +103,5 @@ RecursiveMutex::RecursiveMutex() : Mutex(true) {} -#endif +#endif // C++11 diff --git a/src/threading/mutex.h b/src/threading/mutex.h index dadbd050c..fb5c029fc 100644 --- a/src/threading/mutex.h +++ b/src/threading/mutex.h @@ -26,14 +26,15 @@ DEALINGS IN THE SOFTWARE. #ifndef THREADING_MUTEX_H #define THREADING_MUTEX_H -// Windows std::mutex is much slower than the critical section API -#if __cplusplus >= 201103L && !defined(_WIN32) +#include "threads.h" + +#if USE_CPP11_MUTEX #include using Mutex = std::mutex; using RecursiveMutex = std::recursive_mutex; #else -#ifdef _WIN32 +#if USE_WIN_MUTEX #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif @@ -41,7 +42,7 @@ DEALINGS IN THE SOFTWARE. #define WIN32_LEAN_AND_MEAN #endif #include -#else // pthread +#else #include #endif @@ -59,9 +60,9 @@ protected: Mutex(bool recursive); void init_mutex(bool recursive); private: -#ifdef _WIN32 +#if USE_WIN_MUTEX CRITICAL_SECTION mutex; -#else // pthread +#else pthread_mutex_t mutex; #endif @@ -76,6 +77,6 @@ public: DISABLE_CLASS_COPY(RecursiveMutex); }; -#endif // C++11 +#endif // C++11 #endif diff --git a/src/threading/mutex_auto_lock.h b/src/threading/mutex_auto_lock.h index 25caf7e14..d79c68a93 100644 --- a/src/threading/mutex_auto_lock.h +++ b/src/threading/mutex_auto_lock.h @@ -26,7 +26,9 @@ DEALINGS IN THE SOFTWARE. #ifndef THREADING_MUTEX_AUTO_LOCK_H #define THREADING_MUTEX_AUTO_LOCK_H -#if __cplusplus >= 201103L +#include "threads.h" + +#if USE_CPP11_MUTEX #include using MutexAutoLock = std::unique_lock; using RecursiveMutexAutoLock = std::unique_lock; diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index 0cd536795..fbe4ba1f3 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -198,7 +198,7 @@ bool Thread::kill() m_running = false; -#ifdef _WIN32 +#if USE_WIN_THREADS TerminateThread(m_thread_handle, 0); CloseHandle(m_thread_handle); #else @@ -310,10 +310,16 @@ void Thread::setName(const std::string &name) unsigned int Thread::getNumberOfProcessors() { -#if __cplusplus >= 201103L +#if USE_CPP11_THREADS return std::thread::hardware_concurrency(); +#elif USE_WIN_THREADS + + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; + #elif defined(_SC_NPROCESSORS_ONLN) return sysconf(_SC_NPROCESSORS_ONLN); @@ -335,12 +341,6 @@ unsigned int Thread::getNumberOfProcessors() return get_nprocs(); -#elif defined(_WIN32) - - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; - #elif defined(PTW32_VERSION) || defined(__hpux) return pthread_num_processors_np(); @@ -359,7 +359,7 @@ bool Thread::bindToProcessor(unsigned int proc_number) return false; -#elif defined(_WIN32) +#elif USE_WIN_THREADS return SetThreadAffinityMask(getThreadHandle(), 1 << proc_number); @@ -407,7 +407,7 @@ bool Thread::bindToProcessor(unsigned int proc_number) bool Thread::setPriority(int prio) { -#if defined(_WIN32) +#if USE_WIN_THREADS return SetThreadPriority(getThreadHandle(), prio); diff --git a/src/threading/thread.h b/src/threading/thread.h index de800ecb7..14a0e13ab 100644 --- a/src/threading/thread.h +++ b/src/threading/thread.h @@ -32,9 +32,6 @@ DEALINGS IN THE SOFTWARE. #include "threads.h" #include -#if USE_CPP11_THREADS - #include // for std::thread -#endif #ifdef _AIX #include // for tid_t #endif @@ -157,9 +154,11 @@ private: Atomic m_running; Mutex m_mutex; -#ifndef USE_CPP11_THREADS +#if USE_CPP11_THREADS + std::thread *m_thread_obj; +#else threadhandle_t m_thread_handle; -# if _WIN32 +# if USE_WIN_THREADS threadid_t m_thread_id; # endif #endif @@ -172,10 +171,6 @@ private: tid_t m_kernel_thread_id; #endif -#if USE_CPP11_THREADS - std::thread *m_thread_obj; -#endif - DISABLE_CLASS_COPY(Thread); }; diff --git a/src/threads.h b/src/threads.h index d4306f631..ce98593cd 100644 --- a/src/threads.h +++ b/src/threads.h @@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define THREADS_HEADER // -// Determine which threading API we will use +// Determine which threading APIs we will use // #if __cplusplus >= 201103L #define USE_CPP11_THREADS 1 @@ -31,11 +31,27 @@ with this program; if not, write to the Free Software Foundation, Inc., #define USE_POSIX_THREADS 1 #endif +#if defined(_WIN32) + // Prefer critical section API because std::mutex is much slower on Windows + #define USE_WIN_MUTEX 1 +#elif __cplusplus >= 201103L + #define USE_CPP11_MUTEX 1 +#else + #define USE_POSIX_MUTEX 1 +#endif + /////////////// #if USE_CPP11_THREADS #include +#elif USE_POSIX_THREADS + #include +#else + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include #endif #include "threading/mutex.h"