-/* $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();
+ 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