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.
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);
#endif
}
-#if __cplusplus < 201103L
+#ifndef USE_CPP11_MUTEX
Event::~Event()
{
-#ifdef _WIN32
+#if USE_WIN_MUTEX
CloseHandle(event);
#else
pthread_cond_destroy(&cv);
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);
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);
#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
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;
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)
void Mutex::init_mutex(bool recursive)
{
-#ifdef _WIN32
+#if USE_WIN_MUTEX
// Windows critical sections are recursive by default
UNUSED(recursive);
Mutex::~Mutex()
{
-#ifdef _WIN32
+#if USE_WIN_MUTEX
DeleteCriticalSection(&mutex);
#else
int ret = pthread_mutex_destroy(&mutex);
void Mutex::lock()
{
-#ifdef _WIN32
+#if USE_WIN_MUTEX
EnterCriticalSection(&mutex);
#else
int ret = pthread_mutex_lock(&mutex);
void Mutex::unlock()
{
-#ifdef _WIN32
+#if USE_WIN_MUTEX
LeaveCriticalSection(&mutex);
#else
int ret = pthread_mutex_unlock(&mutex);
: Mutex(true)
{}
-#endif
+#endif // C++11
#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
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
-#else // pthread
+#else
#include <pthread.h>
#endif
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
DISABLE_CLASS_COPY(RecursiveMutex);
};
-#endif // C++11
+#endif // C++11
#endif
#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>;
m_running = false;
-#ifdef _WIN32
+#if USE_WIN_THREADS
TerminateThread(m_thread_handle, 0);
CloseHandle(m_thread_handle);
#else
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);
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();
return false;
-#elif defined(_WIN32)
+#elif USE_WIN_THREADS
return SetThreadAffinityMask(getThreadHandle(), 1 << proc_number);
bool Thread::setPriority(int prio)
{
-#if defined(_WIN32)
+#if USE_WIN_THREADS
return SetThreadPriority(getThreadHandle(), prio);
#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
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
tid_t m_kernel_thread_id;
#endif
-#if USE_CPP11_THREADS
- std::thread *m_thread_obj;
-#endif
-
DISABLE_CLASS_COPY(Thread);
};
#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
#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"