Fix C++11 Windows build of threading code
authorsfan5 <sfan5@live.de>
Thu, 6 Oct 2016 19:13:04 +0000 (21:13 +0200)
committersfan5 <sfan5@live.de>
Thu, 6 Oct 2016 20:37:30 +0000 (22:37 +0200)
The initial problem was that mutex_auto_lock.h tries to use std::unique_lock<std::mutex>
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
src/threading/event.h
src/threading/mutex.cpp
src/threading/mutex.h
src/threading/mutex_auto_lock.h
src/threading/thread.cpp
src/threading/thread.h
src/threads.h

index 165f9d83f9563d64760edc2cfe323ad74683557d..0d5928f105ae89ed24ce5bd830af8bc574fe81d2 100644 (file)
@@ -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);
index dd51645767aa57544260f1138dd07c93aa5b15d8..26cb8997aa57831c4e745282e3fade3bfe43685d 100644 (file)
@@ -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 <condition_variable>
        #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 <windows.h>
-#else
-       #include <pthread.h>
 #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;
index f2b07bec374b354420e8c3691a83e489b46e587d..0908b5d3797f2219e1d8e8f09a7d8071edda7b8d 100644 (file)
@@ -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 <cassert>
-#endif
+#include <cassert>
 
 #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
 
index dadbd050c051d8fc6bd20236d40672242ae56f04..fb5c029fc0cd9a432a68c61944863c1e8322071d 100644 (file)
@@ -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 <mutex>
        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 <windows.h>
-#else // pthread
+#else
        #include <pthread.h>
 #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
index 25caf7e140d9d7bfbbd89036c46cd0275d473678..d79c68a939f7586741fe64d1c91aa9e27d90a4e4 100644 (file)
@@ -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 <mutex>
        using MutexAutoLock = std::unique_lock<std::mutex>;
        using RecursiveMutexAutoLock = std::unique_lock<std::recursive_mutex>;
index 0cd536795f6eab1df44c6f05825fde31b2e687ea..fbe4ba1f395a07214488c23ad0709057afa8dad0 100644 (file)
@@ -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);
 
index de800ecb7e14359ea370bd67cd09fbcfb4ec6c0b..14a0e13ab66f14e88ab3ac72c3144bfeb1984053 100644 (file)
@@ -32,9 +32,6 @@ DEALINGS IN THE SOFTWARE.
 #include "threads.h"
 
 #include <string>
-#if USE_CPP11_THREADS
-       #include <thread> // for std::thread
-#endif
 #ifdef _AIX
        #include <sys/thread.h> // for tid_t
 #endif
@@ -157,9 +154,11 @@ private:
        Atomic<bool> 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);
 };
 
index d4306f631a966132f926ed56f7602b25a66ea8dc..ce98593cd2771501bd274d6e4fc851906e2ca0ab 100644 (file)
@@ -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 <thread>
+#elif USE_POSIX_THREADS
+       #include <pthread.h>
+#else
+       #ifndef WIN32_LEAN_AND_MEAN
+               #define WIN32_LEAN_AND_MEAN
+       #endif
+       #include <windows.h>
 #endif
 
 #include "threading/mutex.h"