From a23176e6d3399bbeb75cf6a173543bf5d5f85187 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 22 Apr 2013 13:54:32 +0300 Subject: [PATCH] Make the Thread state machine more strict Trying to re-launch a thread after it has finished now throws a logic_error. Added a state to indicate the thread having finished. --- source/core/thread.cpp | 39 ++++++++++++++++++++++++--------------- source/core/thread.h | 17 ++++++++++++++++- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/source/core/thread.cpp b/source/core/thread.cpp index cfc0c37..6c542e6 100644 --- a/source/core/thread.cpp +++ b/source/core/thread.cpp @@ -4,8 +4,11 @@ #include #include #endif +#include #include "thread.h" +using namespace std; + namespace Msp { struct Thread::Private @@ -19,33 +22,35 @@ struct Thread::Private Private(): handle(0) { } #ifdef WIN32 - static DWORD WINAPI main_wrapper(void *t) - { reinterpret_cast(t)->main(); return 0; } + static DWORD WINAPI #else - static void *main_wrapper(void *t) - { reinterpret_cast(t)->main(); return 0; } + static void * #endif + main_wrapper(void *a) + { + Thread *t = reinterpret_cast(a); + t->main(); + t->state_ = FINISHED; + return 0; + } }; Thread::Thread(): priv_(new Private), - launched_(false) + state_(PENDING) { } Thread::~Thread() { - if(launched_) - { - kill(); - join(); - } + kill(); + join(); delete priv_; } void Thread::join() { - if(!launched_) + if(state_>=JOINED) return; #ifdef WIN32 @@ -53,22 +58,26 @@ void Thread::join() #else pthread_join(priv_->handle, 0); #endif - launched_ = false; + state_ = JOINED; } void Thread::kill() { + if(state_!=RUNNING) + return; + #ifdef WIN32 TerminateThread(priv_->handle, 0); #else pthread_kill(priv_->handle, SIGKILL); #endif + state_ = KILLED; } void Thread::launch() { - if(launched_) - return; + if(state_>=RUNNING) + throw logic_error("already launched"); #ifdef WIN32 DWORD dummy; // Win9x needs the lpTthreadId parameter @@ -76,7 +85,7 @@ void Thread::launch() #else pthread_create(&priv_->handle, 0, &Private::main_wrapper, this); #endif - launched_ = true; + state_ = RUNNING; } } // namespace Msp diff --git a/source/core/thread.h b/source/core/thread.h index ae25707..81494ea 100644 --- a/source/core/thread.h +++ b/source/core/thread.h @@ -15,8 +15,17 @@ class Thread private: struct Private; + enum State + { + PENDING, + RUNNING, + FINISHED, + KILLED, + JOINED + }; + Private *priv_; - bool launched_; + State state_; protected: Thread(); @@ -26,6 +35,9 @@ private: public: virtual ~Thread(); + /** Indicates whether the thread has finished running. */ + bool is_finished() { return state_>=FINISHED; } + /** Waits for the thread to exit. Calling this from the thread will cause a deadlock. */ void join(); @@ -33,8 +45,11 @@ public: /** Violently terminates the thread. This should only be used as a last resort, as the thread gets no chance to clean up. */ void kill(); + protected: + /** Starts the thread. Can only be called once for each Thread instance. */ void launch(); + virtual void main() = 0; }; -- 2.45.2