1 /**************************************************************************
3 * Copyright 2011-2012 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
27 * OS native thread abstraction.
29 * Mimics C++11 threads.
32 #ifndef _OS_THREAD_HPP_
33 #define _OS_THREAD_HPP_
44 * These features are not supported on Windows XP
46 #define USE_WIN32_DECLSPEC_THREAD 0
47 #define USE_WIN32_CONDITION_VARIABLES 0
54 * - http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Thread_002dLocal.html
55 * - http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
57 #if !defined(_WIN32) || USE_WIN32_DECLSPEC_THREAD
58 # if defined(_MSC_VER)
59 # define OS_THREAD_SPECIFIC_PTR(_type) __declspec(thread) _type *
60 # elif defined(__GNUC__)
61 # define OS_THREAD_SPECIFIC_PTR(_type) __thread _type *
64 #if !defined(OS_THREAD_SPECIFIC_PTR)
65 # define OS_THREAD_SPECIFIC_PTR(_type) os::thread_specific_ptr< _type >
73 * Base class for mutex and recursive_mutex.
79 typedef CRITICAL_SECTION native_handle_type;
81 typedef pthread_mutex_t native_handle_type;
86 InitializeCriticalSection(&_native_handle);
88 pthread_mutexattr_t attr;
89 pthread_mutexattr_init(&attr);
90 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
91 pthread_mutex_init(&_native_handle, &attr);
92 pthread_mutexattr_destroy(&attr);
98 DeleteCriticalSection(&_native_handle);
100 pthread_mutex_destroy(&_native_handle);
107 EnterCriticalSection(&_native_handle);
109 pthread_mutex_lock(&_native_handle);
116 LeaveCriticalSection(&_native_handle);
118 pthread_mutex_unlock(&_native_handle);
122 native_handle_type & native_handle() {
123 return _native_handle;
127 native_handle_type _native_handle;
132 * Same interface as std::mutex.
134 class mutex : public _base_mutex
140 InitializeCriticalSection(&_native_handle);
142 pthread_mutex_init(&_native_handle, NULL);
149 * Same interface as std::recursive_mutex.
151 class recursive_mutex : public _base_mutex
155 recursive_mutex(void) {
157 InitializeCriticalSection(&_native_handle);
159 pthread_mutexattr_t attr;
160 pthread_mutexattr_init(&attr);
161 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
162 pthread_mutex_init(&_native_handle, &attr);
163 pthread_mutexattr_destroy(&attr);
170 * Same interface as std::unique_lock;
172 template< class Mutex >
176 typedef Mutex mutex_type;
179 unique_lock(mutex_type & mutex) :
211 * Same interface as std::condition_variable
213 class condition_variable
217 # if USE_WIN32_CONDITION_VARIABLES
218 // XXX: Only supported on Vista an higher. Not yet supported by WINE.
219 typedef CONDITION_VARIABLE native_handle_type;
220 native_handle_type _native_handle;
222 // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
227 typedef pthread_cond_t native_handle_type;
228 native_handle_type _native_handle;
232 condition_variable() {
234 # if USE_WIN32_CONDITION_VARIABLES
235 InitializeConditionVariable(&_native_handle);
238 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
241 pthread_cond_init(&_native_handle, NULL);
245 ~condition_variable() {
247 # if USE_WIN32_CONDITION_VARIABLES
253 pthread_cond_destroy(&_native_handle);
260 # if USE_WIN32_CONDITION_VARIABLES
261 WakeConditionVariable(&_native_handle);
268 pthread_cond_signal(&_native_handle);
273 wait(unique_lock<mutex> & lock) {
274 mutex::native_handle_type & mutex_native_handle = lock.mutex()->native_handle();
276 # if USE_WIN32_CONDITION_VARIABLES
277 SleepConditionVariableCS(&_native_handle, &mutex_native_handle, INFINITE);
279 InterlockedIncrement(&cWaiters);
280 LeaveCriticalSection(&mutex_native_handle);
281 WaitForSingleObject(hEvent, INFINITE);
282 EnterCriticalSection(&mutex_native_handle);
283 InterlockedDecrement(&cWaiters);
286 pthread_cond_wait(&_native_handle, &mutex_native_handle);
292 template <typename T>
293 class thread_specific_ptr
303 thread_specific_ptr(void) {
305 dwTlsIndex = TlsAlloc();
307 pthread_key_create(&key, NULL);
311 ~thread_specific_ptr() {
315 pthread_key_delete(key);
323 ptr = TlsGetValue(dwTlsIndex);
325 ptr = pthread_getspecific(key);
327 return static_cast<T*>(ptr);
331 operator T * (void) const
337 operator -> (void) const
343 operator = (T * new_value)
352 TlsSetValue(dwTlsIndex, new_value);
354 pthread_setspecific(key, new_value);
361 * Same interface as std::thread
366 typedef HANDLE native_handle_type;
368 typedef pthread_t native_handle_type;
378 thread(const thread &other) :
379 _native_handle(other._native_handle)
383 template< class Function, class Arg >
384 explicit thread( Function& f, Arg arg ) {
387 _native_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)f, (LPVOID)arg, 0, &id);
389 pthread_create(&_native_handle, NULL, (void *(*) (void *))f, (void *)arg);
394 joinable(void) const {
395 return _native_handle != 0;
401 WaitForSingleObject(_native_handle, INFINITE);
403 pthread_join(_native_handle, NULL);
408 native_handle_type _native_handle;
412 template< class Function, class Arg >
414 ThreadProc(LPVOID lpParameter) {
423 #endif /* _OS_THREAD_HPP_ */