]> 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 810b1f80485197eeb66552707897c89e42356215..6c542e6a6712d4e19323fbd779c401abd7ea4215 100644 (file)
@@ -1,77 +1,91 @@
-/* $Id$
-
-This file is part of libmspcore
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef WIN32
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
 #include <signal.h>
 #endif
+#include <stdexcept>
 #include "thread.h"
 
+using namespace std;
+
 namespace Msp {
 
-/**
-Waits for the thread to exit.  Calling this from the thread will cause a
-deadlock.
-*/
-void Thread::join()
+struct Thread::Private
 {
-       if(!launched_)
-               return;
+#ifdef WIN32
+       HANDLE handle;
+#else
+       pthread_t handle;
+#endif
+
+       Private(): handle(0) { }
 
 #ifdef WIN32
-       WaitForSingleObject(thread_, INFINITE);
+       static DWORD WINAPI
 #else
-       pthread_join(thread_, 0);
+       static void *
 #endif
-       launched_ = false;
-}
+       main_wrapper(void *a)
+       {
+               Thread *t = reinterpret_cast<Thread *>(a);
+               t->main();
+               t->state_ = FINISHED;
+               return 0;
+       }
+};
+
+
+Thread::Thread():
+       priv_(new Private),
+       state_(PENDING)
+{ }
 
-/**
-Requests the thread to terminate gracefully.  Currently unimplemented on win32.
-*/
-void Thread::cancel()
+Thread::~Thread()
 {
-#ifndef WIN32 //XXX
-       pthread_cancel(thread_);
-#endif
+       kill();
+       join();
+       delete priv_;
 }
 
-/**
-Violently terminates the thread.
-*/
-void Thread::kill()
+void Thread::join()
 {
+       if(state_>=JOINED)
+               return;
+
 #ifdef WIN32
-       TerminateThread(thread_, 0);
+       WaitForSingleObject(priv_->handle, INFINITE);
 #else
-       pthread_kill(thread_, SIGKILL);
+       pthread_join(priv_->handle, 0);
 #endif
+       state_ = JOINED;
 }
 
-Thread::~Thread()
+void Thread::kill()
 {
-       if(launched_)
-       {
-               kill();
-               join();
-       }
+       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
-       thread_ = CreateThread(0, 0, &main_, this, 0, &dummy);
+       priv_->handle = CreateThread(0, 0, &Private::main_wrapper, this, 0, &dummy);
 #else
-       pthread_create(&thread_, 0, &main_, this);
+       pthread_create(&priv_->handle, 0, &Private::main_wrapper, this);
 #endif
-       launched_ = true;
+       state_ = RUNNING;
 }
 
 } // namespace Msp