From 7d5f055547e70fa93ee9ac944e62f8d657b9dc55 Mon Sep 17 00:00:00 2001 From: chai Date: Fri, 19 Oct 2018 08:36:44 +0800 Subject: =?UTF-8?q?*=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libjin/Thread/Thread.cpp | 301 ---------------------------------------- src/libjin/Thread/Thread.h | 166 ---------------------- src/libjin/Thread/je_thread.cpp | 301 ++++++++++++++++++++++++++++++++++++++++ src/libjin/Thread/je_thread.h | 166 ++++++++++++++++++++++ src/libjin/Thread/thread.cpp | 301 ---------------------------------------- src/libjin/Thread/thread.h | 166 ---------------------- 6 files changed, 467 insertions(+), 934 deletions(-) delete mode 100644 src/libjin/Thread/Thread.cpp delete mode 100644 src/libjin/Thread/Thread.h create mode 100644 src/libjin/Thread/je_thread.cpp create mode 100644 src/libjin/Thread/je_thread.h delete mode 100644 src/libjin/Thread/thread.cpp delete mode 100644 src/libjin/Thread/thread.h (limited to 'src/libjin/Thread') diff --git a/src/libjin/Thread/Thread.cpp b/src/libjin/Thread/Thread.cpp deleted file mode 100644 index 3f2a50d..0000000 --- a/src/libjin/Thread/Thread.cpp +++ /dev/null @@ -1,301 +0,0 @@ -#include "../configuration.h" -#if LIBJIN_MODULES_THREAD - -#include "Thread.h" - -namespace jin -{ - namespace thread - { - - class Mutex - { - public: - Mutex(); - ~Mutex(); - - void lock(); - void unlock(); - private: - #if LIBJIN_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 LIBJIN_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 LIBJIN_THREAD_SDL - mutex = SDL_CreateMutex(); - #endif - } - - Mutex::~Mutex() - { - #if LIBJIN_THREAD_SDL - SDL_DestroyMutex(mutex); - #endif - } - - void Mutex::lock() - { - #if LIBJIN_THREAD_SDL - SDL_LockMutex(mutex); - #endif - } - - void Mutex::unlock() - { - #if LIBJIN_THREAD_SDL - SDL_UnlockMutex(mutex); - #endif - } - - ////////////////////////////////////////////////////////////////////// - - Conditional::Conditional() - { - #if LIBJIN_THREAD_SDL - cond = SDL_CreateCond(); - #endif - } - - Conditional::~Conditional() - { - #if LIBJIN_THREAD_SDL - SDL_DestroyCond(cond); - #endif - } - - void Conditional::signal() - { - #if LIBJIN_THREAD_SDL - SDL_CondSignal(cond); - #endif - } - - void Conditional::broadcast() - { - #if LIBJIN_THREAD_SDL - SDL_CondBroadcast(cond); - #endif - } - - bool Conditional::wait(Mutex* mutex, int timeout) - { - #if LIBJIN_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 LIBJIN_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 LIBJIN_THREAD_SDL - SDL_WaitThread(handle, nullptr); - #endif - } - #if LIBJIN_THREAD_SDL - handle = SDL_CreateThread(threadRunner, name.c_str(), p); - #elif LIBJIN_THREAD_CPP - handle = new std::thread(); - #endif - return (running = (handle != nullptr)); - } - - void Thread::wait() - { - { - Lock l(mutex); - if (!handle) - return; - } - #if LIBJIN_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 thread -} // namespace jin - -#endif // LIBJIN_MODULES_THREAD \ No newline at end of file diff --git a/src/libjin/Thread/Thread.h b/src/libjin/Thread/Thread.h deleted file mode 100644 index ea50444..0000000 --- a/src/libjin/Thread/Thread.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef __LIBJIN_THREAD_H -#define __LIBJIN_THREAD_H -#include "../configuration.h" -#if LIBJIN_MODULES_THREAD - -#include -#include -#if LIBJIN_THREAD_SDL -# include "SDL2/SDL_thread.h" -#elif LIBJIN_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: - struct Variant - { - enum Type - { - NONE = 0, - INTERGER, - BOOLEAN, - CHARACTER, - CSTRING, - POINTER, - REAL, - }; - Type type; - union - { - int integer; - bool boolean; - char character; - const char* cstring; - void* pointer; - float real; - }; - Variant() :type(NONE) {}; - Variant(const Variant& v){ memcpy(this, &v, sizeof(v)); } - Variant(int i) : integer(i), type(INTERGER) {}; - Variant(float f) : real(f), type(REAL) {}; - Variant(bool b) : boolean(b), type(BOOLEAN) {}; - Variant(char c) : character(c), type(CHARACTER) {}; - Variant(const char* s) : cstring(s), type(CSTRING) {}; - Variant(void* p) : pointer(p), type(POINTER) {}; - }; - - private: - class ThreadData - { - public: - static const int SLOT_ERROR = -1; - static const int SLOT_WARN = -2; - static const int SLOT_INFO = -3; - static const int SLOT_DEBUG = -4; - - ThreadData(Mutex*, Conditional*); - ~ThreadData(); - bool exist(int slot); - void set(int slot, Variant value); - Variant get(int slot); - void remove(int slot); - - Conditional* condition; - Mutex* mutex; - - private: - std::map share; // threads shared value - - }; - - public: - typedef int(*ThreadRunner)(void* obj); - - Thread(const std::string name, ThreadRunner threadfuncs); - ~Thread(); - bool start(void* p); - void wait(); - void send(int slot, const Variant& value); - bool receive(int slot); - Variant fetch(int slot); - Variant demand(int slot); - void remove(int slot); - const char* getName(); - bool isRunning(); - void lock(); - void unlock(); - - protected: - #if LIBJIN_THREAD_SDL - SDL_Thread* handle; // SDL thread - #elif LIBJIN_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, for debugging purposes - /** - * https://stackoverflow.com/questions/149932/naming-conventions-for-threads - * - * Use short names because they don't make the lines in a log file too long. - * - * Create names where the important part is at the beginning. Log viewers in a - * graphical user interface tend to have tables with columns, and the thread - * column is usually small or will be made small by you to read everything else. - * - * Do not use the word "thread" in the thread name because it is obvious. - * - * Make the thread names easily grep-able. Avoid similar sounding thread names - * - * If you have several threads of the same nature, enumerate them with IDs that - * are unique to one execution of the application or one log file, whichever fits - * your logging habits. - * - * Avoid generalizations like "WorkerThread" (how do you name the next 5 worker - * threads?), "GUIThread" (which GUI? is it for one window? for everything?) or - * "Calculation" (what does it calculate?). - * - * If you have a test group that uses thread names to grep your application's log - * files, do not rename your threads after some time. Your testers will hate you for - * doing so. Thread names in well-tested applications should be there to stay. - * - * When you have threads that service a network connection, try to include the target - * network address in the thread name (e.g. channel_123.212.123.3). Don't forget about - * enumeration though if there are multiple connections to the same host. - */ - bool running; // running - - }; - - } // namespace thread -} // namespace jin - -#endif // LIBJIN_MODULES_THREAD -#endif // __LIBJIN_THREAD_H \ No newline at end of file diff --git a/src/libjin/Thread/je_thread.cpp b/src/libjin/Thread/je_thread.cpp new file mode 100644 index 0000000..6bf6f46 --- /dev/null +++ b/src/libjin/Thread/je_thread.cpp @@ -0,0 +1,301 @@ +#include "../core/je_configuration.h" +#if LIBJIN_MODULES_THREAD + +#include "je_thread.h" + +namespace jin +{ + namespace thread + { + + class Mutex + { + public: + Mutex(); + ~Mutex(); + + void lock(); + void unlock(); + private: + #if LIBJIN_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 LIBJIN_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 LIBJIN_THREAD_SDL + mutex = SDL_CreateMutex(); + #endif + } + + Mutex::~Mutex() + { + #if LIBJIN_THREAD_SDL + SDL_DestroyMutex(mutex); + #endif + } + + void Mutex::lock() + { + #if LIBJIN_THREAD_SDL + SDL_LockMutex(mutex); + #endif + } + + void Mutex::unlock() + { + #if LIBJIN_THREAD_SDL + SDL_UnlockMutex(mutex); + #endif + } + + ////////////////////////////////////////////////////////////////////// + + Conditional::Conditional() + { + #if LIBJIN_THREAD_SDL + cond = SDL_CreateCond(); + #endif + } + + Conditional::~Conditional() + { + #if LIBJIN_THREAD_SDL + SDL_DestroyCond(cond); + #endif + } + + void Conditional::signal() + { + #if LIBJIN_THREAD_SDL + SDL_CondSignal(cond); + #endif + } + + void Conditional::broadcast() + { + #if LIBJIN_THREAD_SDL + SDL_CondBroadcast(cond); + #endif + } + + bool Conditional::wait(Mutex* mutex, int timeout) + { + #if LIBJIN_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 LIBJIN_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 LIBJIN_THREAD_SDL + SDL_WaitThread(handle, nullptr); + #endif + } + #if LIBJIN_THREAD_SDL + handle = SDL_CreateThread(threadRunner, name.c_str(), p); + #elif LIBJIN_THREAD_CPP + handle = new std::thread(); + #endif + return (running = (handle != nullptr)); + } + + void Thread::wait() + { + { + Lock l(mutex); + if (!handle) + return; + } + #if LIBJIN_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 thread +} // namespace jin + +#endif // LIBJIN_MODULES_THREAD \ No newline at end of file diff --git a/src/libjin/Thread/je_thread.h b/src/libjin/Thread/je_thread.h new file mode 100644 index 0000000..bdbc093 --- /dev/null +++ b/src/libjin/Thread/je_thread.h @@ -0,0 +1,166 @@ +#ifndef __LIBJIN_THREAD_H +#define __LIBJIN_THREAD_H +#include "../core/je_configuration.h" +#if LIBJIN_MODULES_THREAD + +#include +#include +#if LIBJIN_THREAD_SDL + #include "SDL2/SDL_thread.h" +#elif LIBJIN_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: + struct Variant + { + enum Type + { + NONE = 0, + INTERGER, + BOOLEAN, + CHARACTER, + CSTRING, + POINTER, + REAL, + }; + Type type; + union + { + int integer; + bool boolean; + char character; + const char* cstring; + void* pointer; + float real; + }; + Variant() :type(NONE) {}; + Variant(const Variant& v){ memcpy(this, &v, sizeof(v)); } + Variant(int i) : integer(i), type(INTERGER) {}; + Variant(float f) : real(f), type(REAL) {}; + Variant(bool b) : boolean(b), type(BOOLEAN) {}; + Variant(char c) : character(c), type(CHARACTER) {}; + Variant(const char* s) : cstring(s), type(CSTRING) {}; + Variant(void* p) : pointer(p), type(POINTER) {}; + }; + + private: + class ThreadData + { + public: + static const int SLOT_ERROR = -1; + static const int SLOT_WARN = -2; + static const int SLOT_INFO = -3; + static const int SLOT_DEBUG = -4; + + ThreadData(Mutex*, Conditional*); + ~ThreadData(); + bool exist(int slot); + void set(int slot, Variant value); + Variant get(int slot); + void remove(int slot); + + Conditional* condition; + Mutex* mutex; + + private: + std::map share; // threads shared value + + }; + + public: + typedef int(*ThreadRunner)(void* obj); + + Thread(const std::string name, ThreadRunner threadfuncs); + ~Thread(); + bool start(void* p); + void wait(); + void send(int slot, const Variant& value); + bool receive(int slot); + Variant fetch(int slot); + Variant demand(int slot); + void remove(int slot); + const char* getName(); + bool isRunning(); + void lock(); + void unlock(); + + protected: + #if LIBJIN_THREAD_SDL + SDL_Thread* handle; // SDL thread + #elif LIBJIN_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, for debugging purposes + /** + * https://stackoverflow.com/questions/149932/naming-conventions-for-threads + * + * Use short names because they don't make the lines in a log file too long. + * + * Create names where the important part is at the beginning. Log viewers in a + * graphical user interface tend to have tables with columns, and the thread + * column is usually small or will be made small by you to read everything else. + * + * Do not use the word "thread" in the thread name because it is obvious. + * + * Make the thread names easily grep-able. Avoid similar sounding thread names + * + * If you have several threads of the same nature, enumerate them with IDs that + * are unique to one execution of the application or one log file, whichever fits + * your logging habits. + * + * Avoid generalizations like "WorkerThread" (how do you name the next 5 worker + * threads?), "GUIThread" (which GUI? is it for one window? for everything?) or + * "Calculation" (what does it calculate?). + * + * If you have a test group that uses thread names to grep your application's log + * files, do not rename your threads after some time. Your testers will hate you for + * doing so. Thread names in well-tested applications should be there to stay. + * + * When you have threads that service a network connection, try to include the target + * network address in the thread name (e.g. channel_123.212.123.3). Don't forget about + * enumeration though if there are multiple connections to the same host. + */ + bool running; // running + + }; + + } // namespace thread +} // namespace jin + +#endif // LIBJIN_MODULES_THREAD +#endif // __LIBJIN_THREAD_H \ No newline at end of file diff --git a/src/libjin/Thread/thread.cpp b/src/libjin/Thread/thread.cpp deleted file mode 100644 index 3f2a50d..0000000 --- a/src/libjin/Thread/thread.cpp +++ /dev/null @@ -1,301 +0,0 @@ -#include "../configuration.h" -#if LIBJIN_MODULES_THREAD - -#include "Thread.h" - -namespace jin -{ - namespace thread - { - - class Mutex - { - public: - Mutex(); - ~Mutex(); - - void lock(); - void unlock(); - private: - #if LIBJIN_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 LIBJIN_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 LIBJIN_THREAD_SDL - mutex = SDL_CreateMutex(); - #endif - } - - Mutex::~Mutex() - { - #if LIBJIN_THREAD_SDL - SDL_DestroyMutex(mutex); - #endif - } - - void Mutex::lock() - { - #if LIBJIN_THREAD_SDL - SDL_LockMutex(mutex); - #endif - } - - void Mutex::unlock() - { - #if LIBJIN_THREAD_SDL - SDL_UnlockMutex(mutex); - #endif - } - - ////////////////////////////////////////////////////////////////////// - - Conditional::Conditional() - { - #if LIBJIN_THREAD_SDL - cond = SDL_CreateCond(); - #endif - } - - Conditional::~Conditional() - { - #if LIBJIN_THREAD_SDL - SDL_DestroyCond(cond); - #endif - } - - void Conditional::signal() - { - #if LIBJIN_THREAD_SDL - SDL_CondSignal(cond); - #endif - } - - void Conditional::broadcast() - { - #if LIBJIN_THREAD_SDL - SDL_CondBroadcast(cond); - #endif - } - - bool Conditional::wait(Mutex* mutex, int timeout) - { - #if LIBJIN_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 LIBJIN_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 LIBJIN_THREAD_SDL - SDL_WaitThread(handle, nullptr); - #endif - } - #if LIBJIN_THREAD_SDL - handle = SDL_CreateThread(threadRunner, name.c_str(), p); - #elif LIBJIN_THREAD_CPP - handle = new std::thread(); - #endif - return (running = (handle != nullptr)); - } - - void Thread::wait() - { - { - Lock l(mutex); - if (!handle) - return; - } - #if LIBJIN_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 thread -} // namespace jin - -#endif // LIBJIN_MODULES_THREAD \ No newline at end of file diff --git a/src/libjin/Thread/thread.h b/src/libjin/Thread/thread.h deleted file mode 100644 index ea50444..0000000 --- a/src/libjin/Thread/thread.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef __LIBJIN_THREAD_H -#define __LIBJIN_THREAD_H -#include "../configuration.h" -#if LIBJIN_MODULES_THREAD - -#include -#include -#if LIBJIN_THREAD_SDL -# include "SDL2/SDL_thread.h" -#elif LIBJIN_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: - struct Variant - { - enum Type - { - NONE = 0, - INTERGER, - BOOLEAN, - CHARACTER, - CSTRING, - POINTER, - REAL, - }; - Type type; - union - { - int integer; - bool boolean; - char character; - const char* cstring; - void* pointer; - float real; - }; - Variant() :type(NONE) {}; - Variant(const Variant& v){ memcpy(this, &v, sizeof(v)); } - Variant(int i) : integer(i), type(INTERGER) {}; - Variant(float f) : real(f), type(REAL) {}; - Variant(bool b) : boolean(b), type(BOOLEAN) {}; - Variant(char c) : character(c), type(CHARACTER) {}; - Variant(const char* s) : cstring(s), type(CSTRING) {}; - Variant(void* p) : pointer(p), type(POINTER) {}; - }; - - private: - class ThreadData - { - public: - static const int SLOT_ERROR = -1; - static const int SLOT_WARN = -2; - static const int SLOT_INFO = -3; - static const int SLOT_DEBUG = -4; - - ThreadData(Mutex*, Conditional*); - ~ThreadData(); - bool exist(int slot); - void set(int slot, Variant value); - Variant get(int slot); - void remove(int slot); - - Conditional* condition; - Mutex* mutex; - - private: - std::map share; // threads shared value - - }; - - public: - typedef int(*ThreadRunner)(void* obj); - - Thread(const std::string name, ThreadRunner threadfuncs); - ~Thread(); - bool start(void* p); - void wait(); - void send(int slot, const Variant& value); - bool receive(int slot); - Variant fetch(int slot); - Variant demand(int slot); - void remove(int slot); - const char* getName(); - bool isRunning(); - void lock(); - void unlock(); - - protected: - #if LIBJIN_THREAD_SDL - SDL_Thread* handle; // SDL thread - #elif LIBJIN_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, for debugging purposes - /** - * https://stackoverflow.com/questions/149932/naming-conventions-for-threads - * - * Use short names because they don't make the lines in a log file too long. - * - * Create names where the important part is at the beginning. Log viewers in a - * graphical user interface tend to have tables with columns, and the thread - * column is usually small or will be made small by you to read everything else. - * - * Do not use the word "thread" in the thread name because it is obvious. - * - * Make the thread names easily grep-able. Avoid similar sounding thread names - * - * If you have several threads of the same nature, enumerate them with IDs that - * are unique to one execution of the application or one log file, whichever fits - * your logging habits. - * - * Avoid generalizations like "WorkerThread" (how do you name the next 5 worker - * threads?), "GUIThread" (which GUI? is it for one window? for everything?) or - * "Calculation" (what does it calculate?). - * - * If you have a test group that uses thread names to grep your application's log - * files, do not rename your threads after some time. Your testers will hate you for - * doing so. Thread names in well-tested applications should be there to stay. - * - * When you have threads that service a network connection, try to include the target - * network address in the thread name (e.g. channel_123.212.123.3). Don't forget about - * enumeration though if there are multiple connections to the same host. - */ - bool running; // running - - }; - - } // namespace thread -} // namespace jin - -#endif // LIBJIN_MODULES_THREAD -#endif // __LIBJIN_THREAD_H \ No newline at end of file -- cgit v1.1-26-g67d0