]> git.tdb.fi Git - libs/core.git/blobdiff - source/core/thread.cpp
Make the Thread state machine more strict
[libs/core.git] / source / core / thread.cpp
index cfc0c37573d02a100df148a433a0bf365b76111f..6c542e6a6712d4e19323fbd779c401abd7ea4215 100644 (file)
@@ -4,8 +4,11 @@
 #include <pthread.h>
 #include <signal.h>
 #endif
+#include <stdexcept>
 #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<Thread *>(t)->main(); return 0; }
+       static DWORD WINAPI
 #else
-       static void *main_wrapper(void *t)
-       { reinterpret_cast<Thread *>(t)->main(); return 0; }
+       static void *
 #endif
+       main_wrapper(void *a)
+       {
+               Thread *t = reinterpret_cast<Thread *>(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