diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 12370296b9..e8e45187b7 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -241,6 +241,7 @@ + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index f8915af9a2..878ead5d27 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -85,6 +85,7 @@ + diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h new file mode 100644 index 0000000000..9a045a650b --- /dev/null +++ b/Source/Core/Common/Src/StdConditionVariable.h @@ -0,0 +1,166 @@ + +#ifndef CONDITION_VARIABLE_H_ +#define CONDITION_VARIABLE_H_ + +#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) +#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID + +// GCC 4.4 provides +#include + +#elif defined(__has_include) && __has_include() + +// clang and libc++ provide on OSX. However, the version +// of libc++ bundled with OSX 10.7 and 10.8 is buggy: it uses _ as a variable. +// +// We work around this issue by undefining and redefining _. + +#undef _ +#include +#define _(s) wxGetTranslation((s)) + +#else + +// partial std::condition_variable implementation for win32/pthread + +#include + +#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) +#define USE_RVALUE_REFERENCES +#endif + +#if defined(_WIN32) && defined(_M_X64) +#define USE_CONDITION_VARIABLES +#elif defined(_WIN32) +#define USE_EVENTS +#endif + +namespace std +{ + +class condition_variable +{ +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + typedef CONDITION_VARIABLE native_type; +#elif defined(_WIN32) + typedef HANDLE native_type; +#else + typedef pthread_cond_t native_type; +#endif + +public: + +#ifdef USE_EVENTS + typedef native_type native_handle_type; +#else + typedef native_type* native_handle_type; +#endif + + condition_variable() + { +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + InitializeConditionVariable(&m_handle); +#elif defined(_WIN32) + m_handle = CreateEvent(NULL, false, false, NULL); +#else + pthread_cond_init(&m_handle, NULL); +#endif + } + + ~condition_variable() + { +#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES) + CloseHandle(m_handle); +#elif !defined(_WIN32) + pthread_cond_destroy(&m_handle); +#endif + } + + condition_variable(const condition_variable&) /*= delete*/; + condition_variable& operator=(const condition_variable&) /*= delete*/; + + void notify_one() + { +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + WakeConditionVariable(&m_handle); +#elif defined(_WIN32) + SetEvent(m_handle); +#else + pthread_cond_signal(&m_handle); +#endif + } + + void notify_all() + { +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + WakeAllConditionVariable(&m_handle); +#elif defined(_WIN32) + // TODO: broken + SetEvent(m_handle); +#else + pthread_cond_broadcast(&m_handle); +#endif + } + + void wait(unique_lock& lock) + { +#ifdef _WIN32 + #ifdef USE_SRWLOCKS + SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0); + #elif defined(USE_CONDITION_VARIABLES) + SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE); + #else + // TODO: broken, the unlock and wait need to be atomic + lock.unlock(); + WaitForSingleObject(m_handle, INFINITE); + lock.lock(); + #endif +#else + pthread_cond_wait(&m_handle, lock.mutex()->native_handle()); +#endif + } + + template + void wait(unique_lock& lock, Predicate pred) + { + while (!pred()) + wait(lock); + } + + //template + //cv_status wait_until(unique_lock& lock, + // const chrono::time_point& abs_time); + + //template + // bool wait_until(unique_lock& lock, + // const chrono::time_point& abs_time, + // Predicate pred); + + //template + //cv_status wait_for(unique_lock& lock, + // const chrono::duration& rel_time); + + //template + // bool wait_for(unique_lock& lock, + // const chrono::duration& rel_time, + // Predicate pred); + + native_handle_type native_handle() + { +#ifdef USE_EVENTS + return m_handle; +#else + return &m_handle; +#endif + } + +private: + native_type m_handle; +}; + +} + +#endif +#endif diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index 5ced2b2b3e..1eb671f223 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -22,7 +22,7 @@ // This conflicts with gettext's use of _ as a macro. #undef _ -#include +#include "StdConditionVariable.h" #include #include