diff options
Diffstat (limited to 'src/libjin/Thread')
-rw-r--r-- | src/libjin/Thread/Thread.cpp | 274 | ||||
-rw-r--r-- | src/libjin/Thread/Thread.h | 108 |
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 |