/*] Copyright (c) 2009-2010, Charles McGarvey [************************** **] All rights reserved. * * vi:ts=4 sw=4 tw=75 * * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * **************************************************************************/ #ifndef _MOOF_THREAD_HH_ #define _MOOF_THREAD_HH_ /** * @file Thread.hh * Light C++ wrapper around the SDL threads API. */ #include #include namespace Mf { // // The detach function detaches a separate thread by calling 'func' with // the 'arg' parameter. // typedef SDL_Thread* Thread; typedef boost::function Function; inline int detach_(void* arg) { //Function function = *(Function*)arg; int code = (*(Function*)arg)(); delete (Function*)arg; return code; } inline Thread detachFunction(const Function& function) { Function* fcopy = new Function(function); Thread thread = SDL_CreateThread(detach_, (void*)fcopy); if (thread == 0) delete fcopy; return thread; } inline int waitOnThread(Thread thread) { int i; SDL_WaitThread(thread, &i); return i; } inline void killThread(Thread thread) { SDL_KillThread(thread); } // // The identifier function returns a unique integer for the calling thread. // inline unsigned getThreadIdentifier() { return SDL_ThreadID(); } inline unsigned getThreadIdentifier(Thread thread) { return SDL_GetThreadID(thread); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class Mutex { friend class Condition; public: Mutex() { mMutex = SDL_CreateMutex(); } ~Mutex() { SDL_DestroyMutex(mMutex); } bool acquireLock() { return (SDL_LockMutex(mMutex) == 0); } bool releaseLock() { return (SDL_UnlockMutex(mMutex) == 0); } class Lock { friend class Condition; public: Lock(Mutex& mutex) { mMutex = &mutex; mIsLocked = false; } ~Lock() { if (mIsLocked) release(); } bool acquire() { return (mIsLocked = mMutex->acquireLock()); } bool release() { return mMutex->releaseLock(); mIsLocked = false; } bool isLocked() const { return mIsLocked; } protected: Mutex* mMutex; bool mIsLocked; }; class ScopedLock : public Lock { public: ScopedLock(Mutex& mutex) : Lock(mutex) { acquire(); } }; private: SDL_mutex* mMutex; }; class Condition { public: Condition() { condition_ = SDL_CreateCond(); } ~Condition() { SDL_DestroyCond(condition_); } bool wait(Mutex::Lock& lock) { return (SDL_CondWait(condition_, lock.mMutex->mMutex) == 0); } bool wait(Mutex::Lock& lock, unsigned ms) { // TODO for consistency, this function should take seconds return (SDL_CondWaitTimeout(condition_, lock.mMutex->mMutex, ms) == 0); } bool notify() { return (SDL_CondSignal(condition_) == 0); } bool notifyAll() { return (SDL_CondBroadcast(condition_) == 0); } private: SDL_cond* condition_; }; class Semaphore { public: Semaphore(unsigned int value) { semaphore_ = SDL_CreateSemaphore(value); } ~Semaphore() { SDL_DestroySemaphore(semaphore_); } bool acquireLock() { return (SDL_SemWait(semaphore_) == 0); } bool releaseLock() { return (SDL_SemPost(semaphore_) == 0); } bool tryLock() { return (SDL_SemTryWait(semaphore_) == 0); } bool tryLock(unsigned ms) { // TODO for consistency, this function should take seconds return (SDL_SemWaitTimeout(semaphore_, ms) == 0); } class Lock { public: Lock(Semaphore& semaphore) { semaphore_ = &semaphore; mIsLocked = false; } ~Lock() { if (mIsLocked) release(); } bool acquire() { return (mIsLocked = semaphore_->acquireLock()); } bool release() { return semaphore_->releaseLock(); mIsLocked = false; } bool isLocked() const { return mIsLocked; } protected: Semaphore* semaphore_; bool mIsLocked; }; class ScopedLock : public Lock { public: ScopedLock(Semaphore& semaphore) : Lock(semaphore) { acquire(); } }; private: SDL_sem* semaphore_; }; } // namespace Mf #endif // _MOOF_THREAD_HH_