diff options
author | chai <chaifix@163.com> | 2018-08-07 23:29:28 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2018-08-07 23:29:28 +0800 |
commit | f5e30a91cfe12118d2c5d389687ebb931a196c7c (patch) | |
tree | 8d410f5c4fcf421d18ef0c95dd4b6a8b3e247a46 /src/libjin/Thread/thread.h | |
parent | 2576caf003fdb3162ab8a3c7bf77c38a885c3858 (diff) |
*update
Diffstat (limited to 'src/libjin/Thread/thread.h')
-rw-r--r-- | src/libjin/Thread/thread.h | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/libjin/Thread/thread.h b/src/libjin/Thread/thread.h new file mode 100644 index 0000000..37c978d --- /dev/null +++ b/src/libjin/Thread/thread.h @@ -0,0 +1,165 @@ +#ifndef __JIN_THREAD_H +#define __JIN_THREAD_H +#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: + 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: + 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; + + static const int SLOT_ERROR = -1; + static const int SLOT_WARN = -2; + static const int SLOT_INFO = -3; + static const int SLOT_DEBUG = -4; + + private: + std::map<int, Variant> share; // threads shared value + }; + + public: + typedef void(ThreadRunner)(Thread* thread); + Thread(const std::string name, ThreadRunner threadfuncs); + ~Thread(); + bool start(); + void wait(); + void send(int slot, 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(); + + private: + #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, 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 + + static int ThreadFunciton(void* p); + + }; + +} // thread +} // jin + +#endif // JIN_MODULES_THREAD +#endif // __JIN_THREAD_H
\ No newline at end of file |