]> git.cworth.org Git - apitrace/blob - common/os_thread.hpp
c4bc130d4693b7d9bb201da8675543acdcd4659d
[apitrace] / common / os_thread.hpp
1 /**************************************************************************
2  *
3  * Copyright 2011 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 boost::thread_specific_ptr.
144      */
145     template <typename T>
146     class thread_specific_ptr
147     {
148     private:
149 #ifdef _WIN32
150         DWORD dwTlsIndex;
151 #else
152         pthread_key_t key;
153
154         static void destructor(void *ptr) {
155             delete static_cast<T *>(ptr);
156         }
157 #endif
158
159     public:
160         thread_specific_ptr(void) {
161 #ifdef _WIN32
162             dwTlsIndex = TlsAlloc();
163 #else
164             pthread_key_create(&key, &destructor);
165 #endif
166         }
167
168         ~thread_specific_ptr() {
169 #ifdef _WIN32
170             TlsFree(dwTlsIndex);
171 #else
172             pthread_key_delete(key);
173 #endif
174         }
175
176         T* get(void) const {
177             void *ptr;
178 #ifdef _WIN32
179             ptr = TlsGetValue(dwTlsIndex);
180 #else
181             ptr = pthread_getspecific(key);
182 #endif
183             return static_cast<T*>(ptr);
184         }
185
186         T* operator -> (void) const
187         {
188             return get();
189         }
190
191         T& operator * (void) const
192         {
193             return *get();
194         }
195
196         void reset(T* new_value=0) {
197             T * old_value = get();
198 #ifdef _WIN32
199             TlsSetValue(dwTlsIndex, new_value);
200 #else
201             pthread_setspecific(key, new_value);
202 #endif
203             if (old_value) {
204                 delete old_value;
205             }
206         }
207     };
208
209
210 } /* namespace os */
211
212 #endif /* _OS_THREAD_HPP_ */