X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=common%2Fos_thread.hpp;h=f3ae210053da2b08ef711f516a92a3be433860b1;hb=75af867d17044b6e3992e579c35915e35d2a7e78;hp=f5f4e48a0f60a3d24131e4828ce9740197d7d1b0;hpb=67ec200baea241d55bea33c43fd5194d90d9e401;p=apitrace diff --git a/common/os_thread.hpp b/common/os_thread.hpp index f5f4e48..f3ae210 100644 --- a/common/os_thread.hpp +++ b/common/os_thread.hpp @@ -40,6 +40,12 @@ #endif +/* + * This feature is not supported on Windows XP + */ +#define USE_WIN32_CONDITION_VARIABLES 0 + + /** * Compiler TLS. * @@ -47,13 +53,10 @@ * - http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Thread_002dLocal.html * - http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx */ -#if defined(_MSC_VER) -# define thread_specific __declspec(thread) -#elif defined(__GNUC__) -# define thread_specific __thread +#if defined(HAVE_COMPILER_TLS) +# define OS_THREAD_SPECIFIC_PTR(_type) HAVE_COMPILER_TLS _type * #else -# define thread_specific -# error "Unsupported compiler" +# define OS_THREAD_SPECIFIC_PTR(_type) os::thread_specific_ptr< _type > #endif @@ -203,16 +206,31 @@ namespace os { */ class condition_variable { - public: + private: #ifdef _WIN32 +# if USE_WIN32_CONDITION_VARIABLES + // XXX: Only supported on Vista an higher. Not yet supported by WINE. typedef CONDITION_VARIABLE native_handle_type; + native_handle_type _native_handle; +#else + // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + LONG cWaiters; + HANDLE hEvent; +#endif #else typedef pthread_cond_t native_handle_type; + native_handle_type _native_handle; #endif + public: condition_variable() { #ifdef _WIN32 +# if USE_WIN32_CONDITION_VARIABLES InitializeConditionVariable(&_native_handle); +# else + cWaiters = 0; + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +# endif #else pthread_cond_init(&_native_handle, NULL); #endif @@ -220,7 +238,11 @@ namespace os { ~condition_variable() { #ifdef _WIN32 +# if USE_WIN32_CONDITION_VARIABLES /* No-op */ +# else + CloseHandle(hEvent); +# endif #else pthread_cond_destroy(&_native_handle); #endif @@ -229,7 +251,13 @@ namespace os { inline void signal(void) { #ifdef _WIN32 +# if USE_WIN32_CONDITION_VARIABLES WakeConditionVariable(&_native_handle); +# else + if (cWaiters) { + SetEvent(hEvent); + } +# endif #else pthread_cond_signal(&_native_handle); #endif @@ -239,14 +267,87 @@ namespace os { wait(unique_lock & lock) { mutex::native_handle_type & mutex_native_handle = lock.mutex()->native_handle(); #ifdef _WIN32 +# if USE_WIN32_CONDITION_VARIABLES SleepConditionVariableCS(&_native_handle, &mutex_native_handle, INFINITE); +# else + InterlockedIncrement(&cWaiters); + LeaveCriticalSection(&mutex_native_handle); + WaitForSingleObject(hEvent, INFINITE); + EnterCriticalSection(&mutex_native_handle); + InterlockedDecrement(&cWaiters); +# endif #else pthread_cond_wait(&_native_handle, &mutex_native_handle); #endif } + }; - protected: - native_handle_type _native_handle; + + template + class thread_specific_ptr + { + private: +#ifdef _WIN32 + DWORD dwTlsIndex; +#else + pthread_key_t key; +#endif + + public: + thread_specific_ptr(void) { +#ifdef _WIN32 + dwTlsIndex = TlsAlloc(); +#else + pthread_key_create(&key, NULL); +#endif + } + + ~thread_specific_ptr() { +#ifdef _WIN32 + TlsFree(dwTlsIndex); +#else + pthread_key_delete(key); +#endif + } + + inline T * + get(void) const { + void *ptr; +#ifdef _WIN32 + ptr = TlsGetValue(dwTlsIndex); +#else + ptr = pthread_getspecific(key); +#endif + return static_cast(ptr); + } + + inline + operator T * (void) const + { + return get(); + } + + inline T * + operator -> (void) const + { + return get(); + } + + inline T * + operator = (T * new_value) + { + set(new_value); + return new_value; + } + + inline void + set(T* new_value) { +#ifdef _WIN32 + TlsSetValue(dwTlsIndex, new_value); +#else + pthread_setspecific(key, new_value); +#endif + } }; @@ -268,21 +369,31 @@ namespace os { } inline - thread(thread &other) : + thread(const thread &other) : _native_handle(other._native_handle) { } + inline + ~thread() { + } + template< class Function, class Arg > explicit thread( Function& f, Arg arg ) { #ifdef _WIN32 DWORD id = 0; _native_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)f, (LPVOID)arg, 0, &id); #else - pthread_create(&_native_handle, NULL, ( void *(*) (void *))f, arg); + pthread_create(&_native_handle, NULL, (void *(*) (void *))f, (void *)arg); #endif } + inline thread & + operator =(const thread &other) { + _native_handle = other._native_handle; + return *this; + } + inline bool joinable(void) const { return _native_handle != 0;