]> Dogcows Code - chaz/yoink/blobdiff - src/thread.hh
new classes; yajl library
[chaz/yoink] / src / thread.hh
diff --git a/src/thread.hh b/src/thread.hh
new file mode 100644 (file)
index 0000000..990f9b0
--- /dev/null
@@ -0,0 +1,215 @@
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+ Redistribution   and   use  in  source  and  binary  forms,  with  or  without
+ modification, are permitted provided that the following conditions are met:
+   * Redistributions  of  source  code  must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+   * Redistributions  in binary form must reproduce the above copyright notice,
+     this  list of conditions and the following disclaimer in the documentation
+     and/or other materials provided with the distribution.
+ THIS  SOFTWARE  IS  PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND  ANY  EXPRESS  OR  IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED.  IN  NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES  (INCLUDING,  BUT  NOT  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES;  LOSS  OF  USE,  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _THREAD_HH_
+#define _THREAD_HH_
+
+/**
+ * @file thread.hh
+ * Light C++ wrapper around SDL threads.
+ */
+
+#include <boost/function.hpp>
+#include <SDL/SDL.h>
+
+
+namespace dc {
+namespace thread {
+
+//
+// The detach function detaches a separate thread by calling 'func' with
+// the 'arg' parameter.
+//
+
+typedef SDL_Thread* thread;
+
+typedef boost::function<int(void)> function;
+
+
+int detach_(void* arg)
+{
+       function func = *(function*)arg;
+       int ret = func();
+
+       delete (function*)arg;
+       return ret;
+}
+
+thread detach(const function& func)
+{
+       thread t;
+       function* fcopy = new function(func);
+
+       t = SDL_CreateThread(detach_, (void*)fcopy);
+    if (t == 0) delete fcopy;
+       return t;
+}
+
+
+int wait(thread t)
+{
+       int i;
+       SDL_WaitThread(t, &i);
+       return i;
+}
+
+void kill(thread t)
+{
+       SDL_KillThread(t);
+}
+
+
+//
+// The identifier function returns a unique integer for the calling thread.
+//
+
+unsigned int identifier()
+{
+    return SDL_ThreadID();
+}
+
+unsigned int identifier(thread t)
+{
+    return SDL_GetThreadID(t);
+}
+
+
+// =============================================================================
+
+class mutex
+{
+    friend class condition;
+
+public:
+    mutex() { mutex_ = SDL_CreateMutex(); }
+    ~mutex() { SDL_DestroyMutex(mutex_); }
+
+    bool acquireLock() { return (SDL_LockMutex(mutex_)   == 0); }
+    bool releaseLock() { return (SDL_UnlockMutex(mutex_) == 0); }
+
+    class lock
+    {
+        friend class condition;
+
+    public:
+        lock(mutex& m) { mutex_ = &m; isLocked_ = false; }
+        ~lock() { if (isLocked_) release(); }
+
+        bool acquire() { return (isLocked_ = mutex_->acquireLock()); }
+        bool release() { return mutex_->releaseLock(); isLocked_ = false; }
+        bool isLocked() const { return isLocked_; }
+
+    protected:
+        mutex* mutex_;
+        bool isLocked_;
+    };
+
+    class scoped_lock : public lock
+    {
+        public:
+            scoped_lock(mutex& m) : lock(m) { acquire(); }
+    };
+
+private:
+    SDL_mutex* mutex_;
+};
+
+// =============================================================================
+
+class condition
+{
+public:
+    condition() { condition_ = SDL_CreateCond(); }
+    ~condition() { SDL_DestroyCond(condition_); }
+
+    bool wait(mutex::lock& l)
+       {
+        return (SDL_CondWait(condition_, l.mutex_->mutex_) == 0);
+    }
+    bool wait(mutex::lock& l, unsigned ms)
+       {
+               // TODO: For consistency, this function should take seconds, not ms.
+        return (SDL_CondWaitTimeout(condition_, l.mutex_->mutex_, 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 tryLock()     { return (SDL_SemTryWait(semaphore_) == 0); }
+       bool tryLock(unsigned ms)
+       {
+               // TODO: For consistency, this function should take seconds, not ms.
+               return (SDL_SemWaitTimeout(semaphore_, ms) == 0);
+       }
+    bool releaseLock() { return (SDL_SemPost(semaphore_) == 0); }
+    
+    class lock
+    {
+    public:
+        lock(semaphore& m) { semaphore_ = &m; isLocked_ = false; }
+        ~lock() { if (isLocked_) release(); }
+        
+        bool acquire() { return (isLocked_ = semaphore_->acquireLock()); }
+        bool release() { return semaphore_->releaseLock(); isLocked_ = false; }
+        bool isLocked() const { return isLocked_; }
+        
+    protected:
+        semaphore* semaphore_;
+        bool isLocked_;
+    };
+    
+    class scoped_lock : public lock
+    {
+    public:
+        scoped_lock(semaphore& m) : lock(m) { acquire(); }
+    };
+
+private:
+    SDL_sem* semaphore_;
+};
+
+
+} // namespace thread
+} // namespace dc
+
+
+#endif // _THREAD_HH_
+
This page took 0.018902 seconds and 4 git commands to generate.