aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Thread
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-08-07 00:17:24 +0800
committerchai <chaifix@163.com>2018-08-07 00:17:24 +0800
commite4eeedbd6faaef380b58236745856b50cebf4461 (patch)
tree9284fe65848c41526d1d429400c425e47b888504 /src/libjin/Thread
parentf5e72dd12fc47f082a4f6d14090391410aa8a9f1 (diff)
*update
Diffstat (limited to 'src/libjin/Thread')
-rw-r--r--src/libjin/Thread/Thread.cpp67
-rw-r--r--src/libjin/Thread/Thread.h129
2 files changed, 123 insertions, 73 deletions
diff --git a/src/libjin/Thread/Thread.cpp b/src/libjin/Thread/Thread.cpp
index 06975f7..374778b 100644
--- a/src/libjin/Thread/Thread.cpp
+++ b/src/libjin/Thread/Thread.cpp
@@ -23,6 +23,7 @@ namespace thread
friend class Conditional;
};
+ // ̼߳signal wait
class Conditional
{
public:
@@ -43,15 +44,19 @@ namespace thread
Lock(Mutex* m) : mutex(m) {
mutex->lock();
}
+
Lock(Mutex& m) : mutex(&m) {
mutex->lock();
}
+
~Lock() {
mutex->unlock();
}
private:
Mutex* mutex;
+
Lock(Lock&) {}
+
};
//////////////////////////////////////////////////////////////////////
@@ -137,33 +142,43 @@ namespace thread
{
}
- void Thread::ThreadData::set(std::string name, Value value)
+ void Thread::ThreadData::set(int slot, Variant value)
{
- //if (share.count(name) != 0);
- share[name] = value;
+ Lock l(mutex);
+ share[slot] = value;
}
- Thread::Value Thread::ThreadData::get(std::string name)
+ Thread::Variant Thread::ThreadData::get(int slot)
{
- return share[name];
+ Lock l(mutex);
+ return share[slot];
}
- bool Thread::ThreadData::exist(const std::string& name)
+ bool Thread::ThreadData::exist(int slot)
{
- return share.count(name) == 1;
+ Lock l(mutex);
+ return share.count(slot) == 1;
}
- void Thread::ThreadData::remove(std::string name)
+ void Thread::ThreadData::remove(int slot)
{
Lock l(mutex);
- if (exist(name))
+ if (exist(slot))
{
- share.erase(name);
+ share.erase(slot);
}
}
//////////////////////////////////////////////////////////////////////
+ int Thread::ThreadFunciton(void* p)
+ {
+ Thread* thread = (Thread*)p;
+ if (thread->threadRunner != nullptr)
+ thread->threadRunner(thread);
+ return 0;
+ }
+
Thread::Thread(const std::string tname, ThreadRunner runner)
: name(tname)
, running(false)
@@ -204,7 +219,7 @@ namespace thread
#endif
}
#if JIN_THREAD_SDL
- handle = SDL_CreateThread(threadRunner, name.c_str(), this);
+ handle = SDL_CreateThread(ThreadFunciton, name.c_str(), this);
#elif JIN_THREAD_CPP
handle = new std::thread();
#endif
@@ -238,35 +253,45 @@ namespace thread
mutex->unlock();
}
- void Thread::send(std::string name, Value value)
+ void Thread::send(int slot, Variant value)
{
lock();
- common->set(name, value);
+ common->set(slot, value);
unlock();
condition->broadcast();
}
- bool Thread::receive(std::string name)
+ bool Thread::receive(int slot)
{
- return common->exist(name);
+ return common->exist(slot);
}
- Thread::Value Thread::fetch(std::string name)
+ Thread::Variant Thread::fetch(int slot)
{
- Thread::Value v = common->get(name);
+ Thread::Variant v = common->get(slot);
return v;
}
- Thread::Value Thread::demand(std::string name)
+ 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(name))
+ while (!common->exist(slot))
{
- if (common->exist("error"))
+ if (common->exist(ThreadData::SLOT_ERROR))
return 0;
condition->wait(mutex);
}
- Thread::Value v = common->get(name);
+ Thread::Variant v = common->get(slot);
unlock();
return v;
}
diff --git a/src/libjin/Thread/Thread.h b/src/libjin/Thread/Thread.h
index 4996705..aeb0d9e 100644
--- a/src/libjin/Thread/Thread.h
+++ b/src/libjin/Thread/Thread.h
@@ -17,54 +17,48 @@ namespace jin
{
namespace thread
{
- /*
- * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ
- * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ
- * ָһԹԴзʵĴ룬һֻƻ㷨һ򡢽̡߳̿ӵжٽ򣬵Dz
- * һӦûҪ˻ƵԴУꡢСжϴڶеĴ
- * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ
- * ߣ߻ָѣ
- */
+ /**
+ * ӢӢ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.
- */
+ /**
+ * 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:
- union Value
+
+ union Variant
{
- enum
- {
- INTEGER,
- REAL,
- BOOL,
- STRING,
- POINTER
- } type;
-
int integer;
- float real;
bool boolean;
+ char character;
const char* cstring;
void* pointer;
+ float real;
- 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) {};
+ Variant() {};
+ Variant(int i) : integer(i) {};
+ Variant(float f) : real(f) {};
+ Variant(bool b) : boolean(b) {};
+ Variant(char c) : character(c) {};
+ Variant(const char* s) : cstring(s) {};
+ Variant(void* p) : pointer(p) {};
};
private:
@@ -73,36 +67,36 @@ namespace thread
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);
+ 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;
+
private:
- std::map<std::string, Value> share; // threads shared value
- std::map<std::string, void*> sharevalue;
+ std::map<int, Variant> share; // threads shared value
};
public:
- typedef int(ThreadRunner)(void* /*ThreadData*/);
+ typedef void(ThreadRunner)(Thread* thread);
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);
+ void send(int slot, Variant value);
+ bool receive(int slot);
+ Variant fetch(int slot);
+ Variant demand(int slot);
const char* getName();
bool isRunning();
- //void kill();
- //Value peek();
-
- private:
void lock();
void unlock();
+
+ private:
#if JIN_THREAD_SDL
SDL_Thread* handle; // SDL thread
#elif JIN_THREAD_CPP
@@ -112,9 +106,40 @@ namespace thread
Conditional* condition; // condition variable
ThreadRunner* threadRunner; // thread function
ThreadData* common; // threads common data
- const std::string name; // thread name
+ 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