aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/threads/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/threads/thread.cpp')
-rw-r--r--src/libjin/threads/thread.cpp301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/libjin/threads/thread.cpp b/src/libjin/threads/thread.cpp
new file mode 100644
index 0000000..1c35efb
--- /dev/null
+++ b/src/libjin/threads/thread.cpp
@@ -0,0 +1,301 @@
+#include "../core/configuration.h"
+#if defined(jin_thread)
+
+#include "thread.h"
+
+namespace JinEngine
+{
+ namespace Threads
+ {
+
+ class Mutex
+ {
+ public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+ private:
+ #if jin_thread == jin_thread_sdl
+ SDL_mutex* mutex;
+ #endif
+ friend class Conditional;
+ };
+
+ // ̼߳signal wait
+ class Conditional
+ {
+ public:
+ Conditional();
+ ~Conditional();
+ void signal();
+ void broadcast();
+ bool wait(Mutex* mutex, int timeout = -1);
+ private:
+ #if jin_thread == jin_thread_sdl
+ SDL_cond* cond;
+ #endif
+ };
+
+ class Lock
+ {
+ public:
+ Lock(Mutex* m) : mutex(m) {
+ mutex->lock();
+ }
+
+ Lock(Mutex& m) : mutex(&m) {
+ mutex->lock();
+ }
+
+ ~Lock() {
+ mutex->unlock();
+ }
+ private:
+ Mutex* mutex;
+
+ Lock(Lock&) {}
+
+ };
+
+ //////////////////////////////////////////////////////////////////////
+
+ Mutex::Mutex()
+ {
+ #if jin_thread == jin_thread_sdl
+ mutex = SDL_CreateMutex();
+ #endif
+ }
+
+ Mutex::~Mutex()
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_DestroyMutex(mutex);
+ #endif
+ }
+
+ void Mutex::lock()
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_LockMutex(mutex);
+ #endif
+ }
+
+ void Mutex::unlock()
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_UnlockMutex(mutex);
+ #endif
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ Conditional::Conditional()
+ {
+ #if jin_thread == jin_thread_sdl
+ cond = SDL_CreateCond();
+ #endif
+ }
+
+ Conditional::~Conditional()
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_DestroyCond(cond);
+ #endif
+ }
+
+ void Conditional::signal()
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_CondSignal(cond);
+ #endif
+ }
+
+ void Conditional::broadcast()
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_CondBroadcast(cond);
+ #endif
+ }
+
+ bool Conditional::wait(Mutex* mutex, int timeout)
+ {
+ #if jin_thread == jin_thread_sdl
+ if (timeout < 0)
+ return !SDL_CondWait(cond, mutex->mutex);
+ else
+ return (SDL_CondWaitTimeout(cond, mutex->mutex, timeout) == 0);
+ #endif
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ Thread::ThreadData::ThreadData(Mutex* m, Conditional* c)
+ : mutex(m)
+ , condition(c)
+ , share()
+ {
+ }
+
+ Thread::ThreadData::~ThreadData()
+ {
+ }
+
+ void Thread::ThreadData::set(int slot, Variant value)
+ {
+ Lock l(mutex);
+ share[slot] = value;
+ }
+
+ Thread::Variant Thread::ThreadData::get(int slot)
+ {
+ Lock l(mutex);
+ return share[slot];
+ }
+
+ bool Thread::ThreadData::exist(int slot)
+ {
+ Lock l(mutex);
+ return share.count(slot) == 1;
+ }
+
+ void Thread::ThreadData::remove(int slot)
+ {
+ Lock l(mutex);
+ if (exist(slot))
+ {
+ share.erase(slot);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ Thread::Thread(const std::string tname, ThreadRunner runner)
+ : name(tname)
+ , running(false)
+ , threadRunner(runner)
+ {
+ mutex = new Mutex();
+ condition = new Conditional();
+ common = new Thread::ThreadData(mutex, condition);
+ }
+
+ Thread::~Thread()
+ {
+ #if jin_thread == jin_thread_sdl
+ #endif
+ }
+
+ const char* Thread::getName()
+ {
+ Lock l(mutex);
+ return name.c_str();
+ };
+
+ bool Thread::isRunning()
+ {
+ Lock l(mutex);
+ return running;
+ };
+
+ bool Thread::start(void* p)
+ {
+ Lock l(mutex);
+ if (running)
+ return false;
+ if (handle)
+ {
+ #if jin_thread == jin_thread_sdl
+ SDL_WaitThread(handle, nullptr);
+ #endif
+ }
+ #if jin_thread == jin_thread_sdl
+ handle = SDL_CreateThread(threadRunner, name.c_str(), p);
+ #elif jin_thread == jin_thread_cpp
+ handle = new std::thread();
+ #endif
+ return (running = (handle != nullptr));
+ }
+
+ void Thread::wait()
+ {
+ {
+ Lock l(mutex);
+ if (!handle)
+ return;
+ }
+ #if jin_thread == jin_thread_sdl
+ SDL_WaitThread(handle, nullptr);
+ #endif
+ Lock l(mutex);
+ running = false;
+ handle = nullptr;
+ }
+
+ void Thread::lock()
+ {
+ if (mutex != nullptr)
+ mutex->lock();
+ }
+
+ void Thread::unlock()
+ {
+ if (mutex != nullptr)
+ mutex->unlock();
+ }
+
+ void Thread::send(int slot, const Variant& value)
+ {
+ lock();
+ common->set(slot, value);
+ unlock();
+ condition->broadcast();
+ }
+
+ bool Thread::receive(int slot)
+ {
+ return common->exist(slot);
+ }
+
+ Thread::Variant Thread::fetch(int slot)
+ {
+ Thread::Variant v = common->get(slot);
+ return v;
+ }
+
+ Thread::Variant Thread::demand(int slot)
+ {
+ /**
+ * pthread_mutex_lock(mtx);
+ * while(pass == 0)
+ * {
+ * pthread_mutex_unlock(mtx);
+ * pthread_cond_just_wait(cv);
+ * pthread_mutex_lock(mtx);
+ * }
+ * pthread_mutex_unlock(mtx);
+ */
+ lock();
+ while (!common->exist(slot))
+ {
+ if (common->exist(ThreadData::SLOT_ERROR))
+ return 0;
+ condition->wait(mutex);
+ }
+ Thread::Variant v = common->get(slot);
+ unlock();
+ return v;
+ }
+
+ void Thread::remove(int slot)
+ {
+ lock();
+ common->remove(slot);
+ unlock();
+ }
+
+ } // namespace Threads
+} // namespace JinEngine
+
+#endif // defined(jin_thread) \ No newline at end of file