aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Thread
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/Thread')
-rw-r--r--src/libjin/Thread/Thread.cpp274
-rw-r--r--src/libjin/Thread/Thread.h108
2 files changed, 379 insertions, 3 deletions
diff --git a/src/libjin/Thread/Thread.cpp b/src/libjin/Thread/Thread.cpp
index a874b0d..ae6498d 100644
--- a/src/libjin/Thread/Thread.cpp
+++ b/src/libjin/Thread/Thread.cpp
@@ -3,6 +3,280 @@
#include "Thread.h"
+namespace jin
+{
+namespace thread
+{
+ class Mutex
+ {
+ public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+ private:
+ #if 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_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_SDL
+ mutex = SDL_CreateMutex();
+ #endif
+ }
+
+ Mutex::~Mutex()
+ {
+ #if JIN_THREAD_SDL
+ SDL_DestroyMutex(mutex);
+ #endif
+ }
+
+ void Mutex::lock()
+ {
+ #if JIN_THREAD_SDL
+ SDL_LockMutex(mutex);
+ #endif
+ }
+
+ void Mutex::unlock()
+ {
+ #if JIN_THREAD_SDL
+ SDL_UnlockMutex(mutex);
+ #endif
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ Conditional::Conditional()
+ {
+ #if JIN_THREAD_SDL
+ cond = SDL_CreateCond();
+ #endif
+ }
+
+ Conditional::~Conditional()
+ {
+ #if JIN_THREAD_SDL
+ SDL_DestroyCond(cond);
+ #endif
+ }
+
+ void Conditional::signal()
+ {
+ #if JIN_THREAD_SDL
+ SDL_CondSignal(cond);
+ #endif
+ }
+
+ void Conditional::broadcast()
+ {
+ #if JIN_THREAD_SDL
+ SDL_CondBroadcast(cond);
+ #endif
+ }
+
+ bool Conditional::wait(Mutex* mutex, int timeout)
+ {
+ #if 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(std::string name, Value value)
+ {
+ //if (share.count(name) != 0);
+ share[name] = value;
+ }
+
+ Thread::Value Thread::ThreadData::get(std::string name)
+ {
+ return share[name];
+ }
+
+ bool Thread::ThreadData::exist(const std::string& name)
+ {
+ return share.count(name) == 1;
+ }
+
+ void Thread::ThreadData::remove(std::string name)
+ {
+ Lock l(mutex);
+ if (exist(name))
+ {
+ share.erase(name);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ 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_SDL
+ #endif
+ }
+
+ const char* Thread::getName()
+ {
+ Lock l(mutex);
+ return name.c_str();
+ };
+
+ bool Thread::isRunning()
+ {
+ Lock l(mutex);
+ return running;
+ };
+
+ bool Thread::start()
+ {
+ Lock l(mutex);
+ if (running)
+ return false;
+ if (handle)
+ {
+ #if JIN_THREAD_SDL
+ SDL_WaitThread(handle, nullptr);
+ #endif
+ }
+ #if JIN_THREAD_SDL
+ handle = SDL_CreateThread(threadRunner, name.c_str(), this);
+ #elif JIN_THREAD_CPP
+ handle = new std::thread();
+ #endif
+ return (running = (handle != nullptr));
+ }
+
+ void Thread::wait()
+ {
+ {
+ Lock l(mutex);
+ if (!handle)
+ return;
+ }
+ #if 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(std::string name, Value value)
+ {
+ lock();
+ common->set(name, value);
+ unlock();
+ condition->broadcast();
+ }
+
+ bool Thread::receive(std::string name)
+ {
+ return common->exist(name);
+ }
+
+ Thread::Value Thread::fetch(std::string name)
+ {
+ Thread::Value v = common->get(name);
+ return v;
+ }
+
+ Thread::Value Thread::demand(std::string name)
+ {
+ lock();
+ while (!common->exist(name))
+ {
+ if (common->exist("error"))
+ return 0;
+ condition->wait(mutex);
+ }
+ Thread::Value v = common->get(name);
+ unlock();
+ return v;
+ }
+
+} // thread
+} // jin
#endif // JIN_MODULES_THREAD \ No newline at end of file
diff --git a/src/libjin/Thread/Thread.h b/src/libjin/Thread/Thread.h
index 2949589..e271fc9 100644
--- a/src/libjin/Thread/Thread.h
+++ b/src/libjin/Thread/Thread.h
@@ -3,19 +3,121 @@
#include "../modules.h"
#if JIN_MODULES_THREAD
+#include <string>
+#include <map>
+#if JIN_THREAD_SDL
+# include "SDL2/SDL_thread.h"
+#elif JIN_THREAD_CPP
+# include <thread>
+# include <mutex>
+# include <condition_variable>
+#endif
+
namespace jin
{
namespace thread
{
+ /*
+ * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ
+ * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ
+ * ָһԹԴзʵĴ룬һֻƻ㷨һ򡢽̡߳̿ӵжٽ򣬵Dz
+ * һӦûҪ˻ƵԴУꡢСжϴڶеĴ
+ * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ
+ * ߣ߻ָѣ
+ */
+ class Mutex;
+ class Conditional;
+ /*
+ * Thread:demand Receive a message from a thread. Wait for the message to exist before returning.
+ * Thread:getName Get the name of a thread.
+ * Thread:kill Forcefully terminate the thread.
+ * Thread:peek Receive a message from a thread, but leave it in the message box.
+ * Thread:receive Receive a message from a thread.
+ * Thread:send Send a message.
+ * Thread:set Set a value.
+ * Thread:start Starts the thread.
+ * Thread:wait Wait for a thread to finish.
+ */
class Thread
{
public:
- Thread();
+ union Value
+ {
+ enum
+ {
+ INTEGER,
+ REAL,
+ BOOL,
+ STRING,
+ POINTER
+ } type;
+
+ int integer;
+ float real;
+ bool boolean;
+ const char* cstring;
+ void* pointer;
+
+ Value() {};
+ Value(int i) : integer(i), type(INTEGER){};
+ Value(float r) : real(r), type(REAL) {};
+ Value(bool b) : boolean(b), type(BOOL) {};
+ Value(const char* cstr) : cstring(cstr), type(STRING) {};
+ Value(void* p) : pointer(p), type(POINTER) {};
+ };
+
+ private:
+ class ThreadData
+ {
+ public:
+ ThreadData(Mutex*, Conditional*);
+ ~ThreadData();
+ bool exist(const std::string& name);
+ void set(std::string name, Value value);
+ Value get(std::string name);
+ void remove(std::string name);
+ Conditional* condition;
+ Mutex* mutex;
+
+ private:
+ std::map<std::string, Value> share; // threads shared value
+ };
+
+ public:
+ typedef int(ThreadRunner)(void* /*ThreadData*/);
+ Thread(const std::string name, ThreadRunner threadfuncs);
+ ~Thread();
+ bool start();
+ void wait();
+ void send(std::string name, Value value);
+ bool receive(std::string name);
+ Value fetch(std::string name);
+ Value demand(std::string name);
+ const char* getName();
+ bool isRunning();
+ //void kill();
+ //Value peek();
+
+ private:
+ void lock();
+ void unlock();
+ #if JIN_THREAD_SDL
+ SDL_Thread* handle; // SDL thread
+ #elif JIN_THREAD_CPP
+ std::thread* handle; // cpp thread
+ #endif
+ Mutex* mutex; // mutex variable
+ Conditional* condition; // condition variable
+ ThreadRunner* threadRunner; // thread function
+ ThreadData* common; // threads common data
+ const std::string name; // thread name
+ bool running; // running
+
};
-}
-}
+} // thread
+} // jin
#endif // JIN_MODULES_THREAD
#endif // __JIN_THREAD_H \ No newline at end of file