]>
Dogcows Code - chaz/yoink/blob - src/moof/thread.hh
09caefd3048800a0cab77380bbceb62743700e96
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
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.
10 **************************************************************************/
14 * Light C++ wrapper around the SDL threads API.
17 #ifndef _MOOF_THREAD_HH_
18 #define _MOOF_THREAD_HH_
20 #include <boost/bind.hpp>
21 #include <boost/function.hpp>
24 #include <moof/math.hh>
31 * Represents a thread which may be running. You cannot instantiate a
32 * thread object directly; new threads are created by detaching functions
33 * using the detach() method. Once a thread is detached, it will continue
34 * running until the function returns. You don't need to keep the thread
35 * object you want to wait() or kill() the thread later.
41 typedef boost::function
<int(void)> function
;
45 * Construct an invalid thread object which has no association with any
52 * Execute a function in a new thread.
53 * \param function The function to execute.
54 * \return The new thread, or an invalid thread if an error occurred.
56 static thread
detach(const function
& function
)
58 thread::function
* fcopy
= new thread::function(function
);
59 SDL_Thread
* thread
= SDL_CreateThread(&thread::run
, (void*)fcopy
);
60 if (thread
== 0) delete fcopy
;
61 return moof::thread(thread
);
66 * Wait for the thread to terminate, getting its return value. The
67 * thread will be invalidated.
68 * \return The integer value returned by the detached function.
73 SDL_WaitThread(thread_
, &i
);
79 * Forcefully kill the thread without giving it a chance to clean up
80 * after itself. The thread will be invalidated. Don't use this.
84 SDL_KillThread(thread_
);
89 * Get whether or not the thread object is associated with a real
91 * \return True if the thread is valid, false otherwise.
100 * Get a unique identifier for this thread, if it is valid.
101 * \return The identifier.
103 uint32_t identifier() const
105 return SDL_GetThreadID(thread_
);
109 * Get the unique identifier of the calling thread.
110 * \return The identifier.
112 static uint32_t current_identifier()
114 return SDL_ThreadID();
120 thread(SDL_Thread
* thread
) :
123 static int run(void* arg
)
125 int code
= (*(function
*)arg
)();
126 delete (function
*)arg
;
136 * An abstract class representing some task that is to be run
144 * Deconstruct the task.
146 virtual ~async_task() {}
149 * Get whether or not the task is done.
150 * \return True if the task is done, false otherwise.
152 virtual bool is_done() const = 0;
157 virtual void run() = 0;
160 * Block the current thread until the task is finished.
161 * \return A value representing the state of the finished task.
163 virtual int wait() = 0;
167 * An asynchronous task that is run to be executed in a separated thread.
174 * Get the thread object the task is executing in.
175 * \return The thread.
177 const class thread
& thread() const { return thread_
; }
180 * Block the current thread until the task thread is finished.
181 * \return The integer value returned by the task function.
185 return thread_
.wait();
191 class thread thread_
;
196 * A mutex to protect sensitive sections of code from threads which might
197 * otherwise cause unpredictable results.
207 mutex_(SDL_CreateMutex()) {}
210 * Deconstruct a mutex.
214 SDL_DestroyMutex(mutex_
);
219 * Block until the calling thread can secure exclusive access to the
220 * code protected by the mutex.
221 * \return True if the lock was acquired, false otherwise.
226 return (SDL_LockMutex(mutex_
) == 0);
230 * Unlock the mutex. Call this after the sensitive block of code to
231 * allow another thread to acquire the lock.
232 * \return True if the mutex was unlocked, false otherwise.
237 return (SDL_UnlockMutex(mutex_
) == 0);
242 * As an alternative method for locking, objects of this class will
243 * automagically release the lock if it is still locked at
244 * deconstruction. Therefore, it's generally safer to use this method
245 * since it makes it much more difficult to forget to unlock a mutex.
253 * \param mutex The mutex.
255 explicit lock(mutex
& mutex
) :
260 * Deconstruct a lock. The lock is automagically released if it is
265 if (is_locked_
) release();
270 * Try to acquire a lock on the mutex.
271 * \return True if the mutex was locked, false otherwise.
275 return (is_locked_
= mutex_
.acquire_lock());
280 * \return True if the mutex was unlocked, false otherwise.
284 bool result
= mutex_
.release_lock();
291 * Get whether or not the mutex is locked.
292 * \return True if the mutex is locked, false otherwise.
294 bool is_locked() const
305 friend class condition
;
309 * This type of lock tries to acquire a lock on the mutex during
310 * construction and releases the lock on deconstruction.
312 class scoped_lock
: private lock
318 * \param mutex The mutex.
320 explicit scoped_lock(mutex
& mutex
) :
327 * Get whether or not the mutex is locked.
328 * \return True if the mutex is locked, false otherwise.
330 bool is_locked() const
332 return lock::is_locked();
341 friend class condition
;
346 * A class representing a condition variable.
353 * Construct a condition.
357 condition_
= SDL_CreateCond();
361 * Deconstruct a condition.
365 SDL_DestroyCond(condition_
);
370 * Unlock the mutex and wait for another thread to notify the thread,
371 * at which point the mutex will be re-locked and the method will
373 * \param mutex The mutex.
374 * \return True if the thread was notified, false otherwise.
376 bool wait(mutex
& mutex
)
378 return (SDL_CondWait(condition_
, mutex
.mutex_
) == 0);
382 * Unlock the mutex associated with a lock and wait for another thread
383 * to notify the thread, at which point the lock will be re-locked and
384 * the method will return.
385 * \param lock The lock.
386 * \return True if the thread was notified, false otherwise.
388 bool wait(mutex::lock
& lock
)
390 return (SDL_CondWait(condition_
, lock
.mutex_
.mutex_
) == 0);
394 * Unlock the mutex and wait for another thread to notify the thread,
395 * at which point the mutex will be re-locked and the method will
396 * return. If the thread was not notified before a certain number of
397 * seconds, the method will return anyway.
398 * \param mutex The mutex.
399 * \param timeout Number of seconds to wait.
400 * \return True if the thread was notified, false otherwise.
402 bool wait(mutex
& mutex
, scalar timeout
)
404 Uint32 ms
= timeout
* SCALAR(1000.0);
405 return (SDL_CondWaitTimeout(condition_
, mutex
.mutex_
, ms
) == 0);
409 * Unlock the mutex associated with a lock and wait for another thread
410 * to notify the thread, at which point the lock will be re-locked and
411 * the method will return. If the thread was not notified before a
412 * certain number of seconds, the method will return anyway.
413 * \param lock The lock.
414 * \param timeout Number of seconds to wait.
415 * \return True if the thread was notified, false otherwise.
417 bool wait(mutex::lock
& lock
, scalar timeout
)
419 Uint32 ms
= timeout
* SCALAR(1000.0);
420 return (SDL_CondWaitTimeout(condition_
,
421 lock
.mutex_
.mutex_
, ms
) == 0);
426 * Notify one other thread that is waiting on the condition.
427 * \return True on success, false otherwise.
431 return (SDL_CondSignal(condition_
) == 0);
435 * Notify all other threads that are waiting on the condition.
436 * \return True on success, false otherwise.
440 return (SDL_CondBroadcast(condition_
) == 0);
446 SDL_cond
* condition_
;
458 * Construct a semaphore.
459 * \param value The initial value of the semaphore.
461 explicit semaphore(uint32_t value
)
463 semaphore_
= SDL_CreateSemaphore(value
);
467 * Deconstruct a semaphore.
471 SDL_DestroySemaphore(semaphore_
);
476 * Block until the calling thread can secure exclusive access to the
477 * code protected by the semaphore.
478 * \return True if the lock was acquired, false otherwise.
483 return (SDL_SemWait(semaphore_
) == 0);
487 * Block until the calling thread can secure exclusive access to the
488 * code protected by the semaphore, or until the timeout expires.
489 * \param timeout Number of seconds to try.
490 * \return True if the lock was acquired, false otherwise.
492 bool acquire_lock(scalar timeout
)
494 Uint32 ms
= timeout
* SCALAR(1000.0);
495 return (SDL_SemWaitTimeout(semaphore_
, ms
) == 0);
499 * Unlock the semaphore. Call this after the sensitive block of code
500 * to allow another thread to acquire the lock.
501 * \return True if the semaphore was unlocked, false otherwise.
506 return (SDL_SemPost(semaphore_
) == 0);
510 * Try to lock the semaphore, but don't block if the lock is not
511 * immediately available.
512 * \return True if the semaphore was locked, false otherwise.
516 return (SDL_SemTryWait(semaphore_
) == 0);
520 * As an alternative method for locking, objects of this class will
521 * automagically release the lock if it is still locked at
522 * deconstruction. Therefore, it's generally safer to use this method
523 * since it makes it much more difficult to forget to unlock a
532 * \param semaphore The semaphore.
534 explicit lock(semaphore
& semaphore
) :
535 semaphore_(semaphore
),
539 * Deconstruct a lock. The lock is automagically released if it is
544 if (is_locked_
) release();
549 * Try to acquire a lock on the semaphore.
550 * \return True if the semaphore was locked, false otherwise.
554 return (is_locked_
= semaphore_
.acquire_lock());
559 * \return True if the semaphore was unlocked, false otherwise.
563 bool result
= semaphore_
.release_lock();
569 * Get whether or not the semaphore is locked.
570 * \return True if the semaphore is locked, false otherwise.
572 bool is_locked() const
580 semaphore
& semaphore_
;
585 * This type of lock tries to acquire a lock on the semaphore during
586 * construction and releases the lock on deconstruction.
588 class scoped_lock
: private lock
594 * \param semaphore The semaphore.
596 explicit scoped_lock(semaphore
& semaphore
) :
603 * Get whether or not the semaphore is locked.
604 * \return True if the semaphore is locked, false otherwise.
606 bool is_locked() const
608 return lock::is_locked();
621 #endif // _MOOF_THREAD_HH_
This page took 0.064838 seconds and 4 git commands to generate.