From 89e7a9ecfad9a54633eb3ebbab1d1f13ad78826f Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 6 Aug 2018 16:22:00 +0800 Subject: *update --- src/libjin/Thread/Thread.cpp | 274 +++++++++++++++++++++++++++++++++++++++++++ src/libjin/Thread/Thread.h | 108 ++++++++++++++++- 2 files changed, 379 insertions(+), 3 deletions(-) (limited to 'src/libjin/Thread') 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 +#include +#if JIN_THREAD_SDL +# include "SDL2/SDL_thread.h" +#elif JIN_THREAD_CPP +# include +# include +# include +#endif + namespace jin { namespace thread { + /* + * 互斥锁(英语:英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源 + * 比如全局变量)进行读写的机制。该目的通过将代码切片成一个一个的临界区域(critical section)达成。临界区域 + * 指的是一块对公共资源进行访问的代码,并非一种机制或是算法。一个程序、进程、线程可以拥有多个临界区域,但是并 + * 不一定会应用互斥锁。需要此机制的资源的例子有:旗标、队列、计数器、中断处理程序等用于在多条并行运行的代码间 + * 传递数据、同步状态等的资源。维护这些资源的同步、一致和完整是很困难的,因为一条线程可能在任何一个时刻被暂停 + * 休眠)或者恢复(唤醒)。 + */ + 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 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 -- cgit v1.1-26-g67d0