]> Dogcows Code - chaz/yoink/blob - src/Moof/Thread.hh
3e0bd829a8affabd059f5b7b376779e7971e4fbf
[chaz/yoink] / src / Moof / Thread.hh
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #ifndef _MOOF_THREAD_HH_
13 #define _MOOF_THREAD_HH_
14
15 /**
16 * @file Thread.hh
17 * Light C++ wrapper around the SDL threads API.
18 */
19
20 #include <boost/function.hpp>
21 #include <SDL/SDL.h>
22
23
24 namespace Mf {
25
26
27 //
28 // The detach function detaches a separate thread by calling 'func' with
29 // the 'arg' parameter.
30 //
31
32 typedef SDL_Thread* Thread;
33
34 typedef boost::function<int(void)> Function;
35
36
37 inline int detach_(void* arg)
38 {
39 //Function function = *(Function*)arg;
40 int code = (*(Function*)arg)();
41
42 delete (Function*)arg;
43 return code;
44 }
45
46 inline Thread detachFunction(const Function& function)
47 {
48 Function* fcopy = new Function(function);
49 Thread thread = SDL_CreateThread(detach_, (void*)fcopy);
50
51 if (thread == 0) delete fcopy;
52 return thread;
53 }
54
55
56 inline int waitOnThread(Thread thread)
57 {
58 int i;
59 SDL_WaitThread(thread, &i);
60 return i;
61 }
62
63 inline void killThread(Thread thread)
64 {
65 SDL_KillThread(thread);
66 }
67
68
69 //
70 // The identifier function returns a unique integer for the calling thread.
71 //
72
73 inline unsigned getThreadIdentifier()
74 {
75 return SDL_ThreadID();
76 }
77
78 inline unsigned getThreadIdentifier(Thread thread)
79 {
80 return SDL_GetThreadID(thread);
81 }
82
83
84 class AsyncTask
85 {
86 public:
87
88 virtual ~AsyncTask() {}
89
90 virtual bool isDone() const = 0;
91
92 virtual void run() = 0;
93 virtual int wait() = 0;
94 };
95
96 class ThreadedTask
97 {
98 public:
99
100 ThreadedTask() :
101 mThread(0) {}
102
103 Thread thread() const { return mThread; }
104
105 int wait()
106 {
107 int code = waitOnThread(mThread);
108 mThread = 0;
109 return code;
110 }
111
112
113 protected:
114
115 Thread mThread;
116 };
117
118
119 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
121 class Mutex
122 {
123 friend class Condition;
124
125 public:
126
127 Mutex()
128 {
129 mMutex = SDL_CreateMutex();
130 }
131 ~Mutex()
132 {
133 SDL_DestroyMutex(mMutex);
134 }
135
136 bool acquireLock()
137 {
138 return (SDL_LockMutex(mMutex) == 0);
139 }
140 bool releaseLock()
141 {
142 return (SDL_UnlockMutex(mMutex) == 0);
143 }
144
145 class Lock
146 {
147 friend class Condition;
148
149 public:
150
151 Lock(Mutex& mutex)
152 {
153 mMutex = &mutex;
154 mIsLocked = false;
155 }
156 ~Lock()
157 {
158 if (mIsLocked) release();
159 }
160
161 bool acquire()
162 {
163 return (mIsLocked = mMutex->acquireLock());
164 }
165 bool release()
166 {
167 return mMutex->releaseLock();
168 mIsLocked = false;
169 }
170
171 bool isLocked() const
172 {
173 return mIsLocked;
174 }
175
176 protected:
177
178 Mutex* mMutex;
179 bool mIsLocked;
180 };
181
182 class ScopedLock : public Lock
183 {
184 public:
185
186 ScopedLock(Mutex& mutex) :
187 Lock(mutex)
188 {
189 acquire();
190 }
191 };
192
193 private:
194
195 SDL_mutex* mMutex;
196 };
197
198
199 class Condition
200 {
201 public:
202
203 Condition()
204 {
205 condition_ = SDL_CreateCond();
206 }
207 ~Condition()
208 {
209 SDL_DestroyCond(condition_);
210 }
211
212 bool wait(Mutex::Lock& lock)
213 {
214 return (SDL_CondWait(condition_, lock.mMutex->mMutex) == 0);
215 }
216 bool wait(Mutex::Lock& lock, unsigned ms)
217 {
218 // TODO for consistency, this function should take seconds
219 return (SDL_CondWaitTimeout(condition_,
220 lock.mMutex->mMutex, ms) == 0);
221 }
222
223 bool notify()
224 {
225 return (SDL_CondSignal(condition_) == 0);
226 }
227 bool notifyAll()
228 {
229 return (SDL_CondBroadcast(condition_) == 0);
230 }
231
232 private:
233
234 SDL_cond* condition_;
235 };
236
237
238 class Semaphore
239 {
240 public:
241
242 Semaphore(unsigned int value)
243 {
244 semaphore_ = SDL_CreateSemaphore(value);
245 }
246 ~Semaphore()
247 {
248 SDL_DestroySemaphore(semaphore_);
249 }
250
251 bool acquireLock()
252 {
253 return (SDL_SemWait(semaphore_) == 0);
254 }
255 bool releaseLock()
256 {
257 return (SDL_SemPost(semaphore_) == 0);
258 }
259
260 bool tryLock()
261 {
262 return (SDL_SemTryWait(semaphore_) == 0);
263 }
264 bool tryLock(unsigned ms)
265 {
266 // TODO for consistency, this function should take seconds
267 return (SDL_SemWaitTimeout(semaphore_, ms) == 0);
268 }
269
270 class Lock
271 {
272 public:
273
274 Lock(Semaphore& semaphore)
275 {
276 semaphore_ = &semaphore;
277 mIsLocked = false;
278 }
279 ~Lock()
280 {
281 if (mIsLocked) release();
282 }
283
284 bool acquire()
285 {
286 return (mIsLocked = semaphore_->acquireLock());
287 }
288 bool release()
289 {
290 return semaphore_->releaseLock(); mIsLocked = false;
291 }
292
293 bool isLocked() const
294 {
295 return mIsLocked;
296 }
297
298 protected:
299
300 Semaphore* semaphore_;
301 bool mIsLocked;
302 };
303
304 class ScopedLock : public Lock
305 {
306 public:
307
308 ScopedLock(Semaphore& semaphore) :
309 Lock(semaphore)
310 {
311 acquire();
312 }
313 };
314
315 private:
316
317 SDL_sem* semaphore_;
318 };
319
320
321 } // namespace Mf
322
323 #endif // _MOOF_THREAD_HH_
324
This page took 0.044136 seconds and 3 git commands to generate.