aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Thread/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/Thread/thread.h')
-rw-r--r--src/libjin/Thread/thread.h165
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