]> git.cworth.org Git - apitrace/blob - common/os_thread.hpp
9d6a9891524564803d844bfe923de13dfd8442c0
[apitrace] / common / os_thread.hpp
1 /**************************************************************************
2  *
3  * Copyright 2011-2012 Jose Fonseca
4  * All Rights Reserved.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 /*
27  * Simple OS abstraction.
28  *
29  * Mimics C++11 / boost threads.
30  */
31
32 #ifndef _OS_THREAD_HPP_
33 #define _OS_THREAD_HPP_
34
35
36 #ifdef _WIN32
37 #include <windows.h>
38 #else
39 #include <pthread.h>
40 #endif
41
42 namespace os {
43
44
45     /**
46      * Base class for mutex and recursive_mutex.
47      */
48     class _base_mutex
49     {
50     public:
51 #ifdef _WIN32
52         typedef CRITICAL_SECTION native_handle_type;
53 #else
54         typedef pthread_mutex_t native_handle_type;
55 #endif
56
57         _base_mutex(void) {
58 #ifdef _WIN32
59             InitializeCriticalSection(&_native_handle);
60 #else
61             pthread_mutexattr_t attr;
62             pthread_mutexattr_init(&attr);
63             pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
64             pthread_mutex_init(&_native_handle, &attr);
65             pthread_mutexattr_destroy(&attr);
66 #endif
67         }
68
69         ~_base_mutex() {
70 #ifdef _WIN32
71             DeleteCriticalSection(&_native_handle);
72 #else
73             pthread_mutex_destroy(&_native_handle);
74 #endif
75         }
76
77         inline void
78         lock(void) {
79 #ifdef _WIN32
80             EnterCriticalSection(&_native_handle);
81 #else
82             pthread_mutex_lock(&_native_handle);
83 #endif
84         }
85
86         inline void
87         unlock(void) {
88 #ifdef _WIN32
89             LeaveCriticalSection(&_native_handle);
90 #else
91             pthread_mutex_unlock(&_native_handle);
92 #endif
93         }
94
95         native_handle_type & native_handle() {
96             return _native_handle;
97         }
98
99     protected:
100         native_handle_type _native_handle;
101     };
102
103
104     /**
105      * Same interface as std::mutex.
106      */
107     class mutex : public _base_mutex
108     {
109     public:
110         inline
111         mutex(void) {
112 #ifdef _WIN32
113             InitializeCriticalSection(&_native_handle);
114 #else
115             pthread_mutex_init(&_native_handle, NULL);
116 #endif
117         }
118     };
119
120
121     /**
122      * Same interface as std::recursive_mutex.
123      */
124     class recursive_mutex : public _base_mutex
125     {
126     public:
127         inline
128         recursive_mutex(void) {
129 #ifdef _WIN32
130             InitializeCriticalSection(&_native_handle);
131 #else
132             pthread_mutexattr_t attr;
133             pthread_mutexattr_init(&attr);
134             pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
135             pthread_mutex_init(&_native_handle, &attr);
136             pthread_mutexattr_destroy(&attr);
137 #endif
138         }
139     };
140
141
142     /**
143      * Same interface as std::unique_lock;
144      */
145     template< class Mutex >
146     class unique_lock
147     {
148     public:
149         typedef Mutex mutex_type;
150
151         inline explicit
152         unique_lock(mutex_type & mutex) :
153             _mutex(&mutex)
154         {
155             _mutex->lock();
156         }
157
158         inline
159         ~unique_lock() {
160             _mutex->unlock();
161         }
162
163         inline void
164         lock() {
165             _mutex->lock();
166         }
167
168         inline void
169         unlock() {
170             _mutex->unlock();
171         }
172
173         mutex_type *
174         mutex() const {
175             return _mutex;
176         }
177
178     protected:
179         mutex_type *_mutex;
180     };
181
182
183     /**
184      * Same interface as std::condition_variable
185      */
186     class condition_variable
187     {
188     public:
189 #ifdef _WIN32
190         /* FIXME */
191 #else
192         typedef pthread_cond_t native_handle_type;
193 #endif
194
195         condition_variable() {
196 #ifdef _WIN32
197             /* FIXME */
198 #else
199             pthread_cond_init(&_native_handle, NULL);
200 #endif
201         }
202
203         ~condition_variable() {
204 #ifdef _WIN32
205             /* FIXME */
206 #else
207             pthread_cond_destroy(&_native_handle);
208 #endif
209         }
210
211         inline void
212         signal(void) {
213 #ifdef _WIN32
214             /* FIXME */
215 #else
216             pthread_cond_signal(&_native_handle);
217 #endif
218         }
219
220         inline void
221         wait(unique_lock<mutex> & lock) {
222 #ifdef _WIN32
223             /* FIXME */
224 #else
225             pthread_cond_wait(&_native_handle, &lock.mutex()->native_handle());
226 #endif
227         }
228
229     protected:
230         native_handle_type _native_handle;
231     };
232
233
234     /**
235      * Same interface as boost::thread_specific_ptr.
236      */
237     template <typename T>
238     class thread_specific_ptr
239     {
240     private:
241 #ifdef _WIN32
242         DWORD dwTlsIndex;
243 #else
244         pthread_key_t key;
245
246         static void destructor(void *ptr) {
247             delete static_cast<T *>(ptr);
248         }
249 #endif
250
251     public:
252         thread_specific_ptr(void) {
253 #ifdef _WIN32
254             dwTlsIndex = TlsAlloc();
255 #else
256             pthread_key_create(&key, &destructor);
257 #endif
258         }
259
260         ~thread_specific_ptr() {
261 #ifdef _WIN32
262             TlsFree(dwTlsIndex);
263 #else
264             pthread_key_delete(key);
265 #endif
266         }
267
268         T* get(void) const {
269             void *ptr;
270 #ifdef _WIN32
271             ptr = TlsGetValue(dwTlsIndex);
272 #else
273             ptr = pthread_getspecific(key);
274 #endif
275             return static_cast<T*>(ptr);
276         }
277
278         T* operator -> (void) const
279         {
280             return get();
281         }
282
283         T& operator * (void) const
284         {
285             return *get();
286         }
287
288         void reset(T* new_value=0) {
289             T * old_value = get();
290 #ifdef _WIN32
291             TlsSetValue(dwTlsIndex, new_value);
292 #else
293             pthread_setspecific(key, new_value);
294 #endif
295             if (old_value) {
296                 delete old_value;
297             }
298         }
299     };
300
301
302     /**
303      * Same interface as std::thread
304      */
305     class thread {
306     public:
307 #ifdef _WIN32
308         /* FIXME */
309 #else
310         typedef pthread_t native_handle_type;
311 #endif
312
313         template< class Function, class Arg >
314         explicit thread( Function& f, Arg & arg ) {
315 #ifdef _WIN32
316             /* FIXME */
317 #else
318             pthread_create(&_native_handle, NULL, f, arg);
319 #endif
320         }
321
322         inline void
323         join() {
324 #ifdef _WIN32
325             /* FIXME */
326 #else
327             pthread_join(_native_handle, NULL);
328 #endif
329         }
330
331     private:
332         native_handle_type _native_handle;
333     };
334
335 } /* namespace os */
336
337 #endif /* _OS_THREAD_HPP_ */