--- a/configure Tue Apr 01 13:28:55 2008 +0000
+++ b/configure Tue Apr 01 13:40:36 2008 +0000
@@ -96,7 +96,7 @@
if ($0 == "MSVC" && "'$os'" != "MSVC") { next; }
if ($0 == "DIRECTMUSIC" && "'$with_direct_music'" == "0") { next; }
if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; }
- if ($0 == "NO_THREADS" && "'$with_threads'" == "0") { next; }
+ if ($0 == "HAVE_THREAD" && "'$with_threads'" == "0") { next; }
skip += 1;
--- a/projects/openttd_vs80.vcproj Tue Apr 01 13:28:55 2008 +0000
+++ b/projects/openttd_vs80.vcproj Tue Apr 01 13:40:36 2008 +0000
@@ -744,7 +744,7 @@
>
</File>
<File
- RelativePath=".\..\src\thread.cpp"
+ RelativePath=".\..\src\thread_win32.cpp"
>
</File>
<File
--- a/projects/openttd_vs90.vcproj Tue Apr 01 13:28:55 2008 +0000
+++ b/projects/openttd_vs90.vcproj Tue Apr 01 13:40:36 2008 +0000
@@ -741,7 +741,7 @@
>
</File>
<File
- RelativePath=".\..\src\thread.cpp"
+ RelativePath=".\..\src\thread_win32.cpp"
>
</File>
<File
--- a/source.list Tue Apr 01 13:28:55 2008 +0000
+++ b/source.list Tue Apr 01 13:40:36 2008 +0000
@@ -79,7 +79,19 @@
squirrel_std.cpp
texteff.cpp
tgp.cpp
-thread.cpp
+#if HAVE_THREAD
+ #if WIN32
+ thread_win32.cpp
+ #else
+ #if OS2
+ thread_os2.cpp
+ #else
+ thread_pthread.cpp
+ #endif
+ #endif
+#else
+ thread_none.cpp
+#endif
tile_map.cpp
#if WIN32
#else
@@ -458,7 +470,7 @@
# AI Core
ai/ai.cpp
ai/ai.h
-#if NO_THREADS
+#if HAVE_THREAD
ai/ai_factory.hpp
ai/ai_gui.cpp
ai/ai_gui.hpp
--- a/src/thread.cpp Tue Apr 01 13:28:55 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,486 +0,0 @@
-/* $Id$ */
-
-/** @file thread.cpp */
-
-#include "stdafx.h"
-#include "thread.h"
-#include "debug.h"
-#include "core/alloc_func.hpp"
-#include <stdlib.h>
-
-#if defined(__AMIGA__) || defined(__MORPHOS__) || defined(PSP) || defined(NO_THREADS)
-OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg) { return NULL; }
-void *OTTDJoinThread(OTTDThread *t) { return NULL; }
-void OTTDExitThread() { NOT_REACHED(); };
-
-#elif defined(__OS2__)
-
-#define INCL_DOS
-#include <os2.h>
-#include <process.h>
-
-struct OTTDThread {
- TID thread;
- OTTDThreadFunc func;
- void *arg;
- void *ret;
-};
-
-static void Proxy(void *arg)
-{
- OTTDThread *t = (OTTDThread *)arg;
- t->ret = t->func(t->arg);
-}
-
-OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
-{
- OTTDThread *t = MallocT<OTTDThread>(1);
-
- if (t == NULL) return NULL;
-
- t->func = function;
- t->arg = arg;
- t->thread = _beginthread(Proxy, NULL, 32768, t);
- if (t->thread != (TID)-1) {
- return t;
- } else {
- free(t);
- return NULL;
- }
-}
-
-void *OTTDJoinThread(OTTDThread *t)
-{
- void *ret;
-
- if (t == NULL) return NULL;
-
- DosWaitThread(&t->thread, DCWW_WAIT);
- ret = t->ret;
- free(t);
- return ret;
-}
-
-void OTTDExitThread()
-{
- _endthread();
-}
-
-#elif defined(UNIX)
-
-#include <pthread.h>
-#include <semaphore.h>
-#include <unistd.h>
-
-struct OTTDThread {
- pthread_t thread;
-};
-
-OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
-{
- OTTDThread *t = MallocT<OTTDThread>(1);
-
- if (t == NULL) return NULL;
-
- if (pthread_create(&t->thread, NULL, function, arg) == 0) {
- return t;
- } else {
- free(t);
- return NULL;
- }
-}
-
-void *OTTDJoinThread(OTTDThread *t)
-{
- void* ret;
-
- if (t == NULL) return NULL;
-
- pthread_join(t->thread, &ret);
- free(t);
- return ret;
-}
-
-void OTTDExitThread()
-{
- pthread_exit(NULL);
-}
-
-
-/**
- * POSIX pthread version for ThreadObject.
- */
-class ThreadObject_pthread : public ThreadObject {
-private:
- pthread_t m_thr; ///< System thread identifier.
- OTTDThreadFunc m_proc; ///< External thread procedure.
- void *m_param; ///< Parameter for the external thread procedure.
- bool m_attached; ///< True if the ThreadObject was attached to an existing thread.
- sem_t m_sem_start; ///< Here the new thread waits before it starts.
- sem_t m_sem_stop; ///< Here the other thread can wait for this thread to end.
-
-public:
- /**
- * Create a pthread and start it, calling proc(param).
- */
- ThreadObject_pthread(OTTDThreadFunc proc, void *param) :
- m_thr(0),
- m_proc(proc),
- m_param(param),
- m_attached(false)
- {
- sem_init(&m_sem_start, 0, 0);
- sem_init(&m_sem_stop, 0, 0);
-
- pthread_create(&m_thr, NULL, &stThreadProc, this);
- sem_post(&m_sem_start);
- }
-
- /**
- * Create a pthread and attach current thread to it.
- */
- ThreadObject_pthread() :
- m_thr(0),
- m_proc(NULL),
- m_param(0),
- m_attached(true)
- {
- sem_init(&m_sem_start, 0, 0);
- sem_init(&m_sem_stop, 0, 0);
-
- m_thr = pthread_self();
- }
-
- /* virtual */ ~ThreadObject_pthread()
- {
- sem_destroy(&m_sem_stop);
- sem_destroy(&m_sem_start);
- };
-
- /* virtual */ bool IsRunning()
- {
- return m_thr != 0;
- }
-
- /* virtual */ bool WaitForStop()
- {
- /* You can't wait on yourself */
- assert(!IsCurrent());
- /* If the thread is not running, waiting is over */
- if (!IsRunning()) return true;
-
- int ret = sem_wait(&m_sem_stop);
- if (ret == 0) {
- /* We have passed semaphore so increment it again */
- sem_post(&m_sem_stop);
- return true;
- }
- return false;
- }
-
- /* virtual */ bool IsCurrent()
- {
- return pthread_self() == m_thr;
- }
-
- /* virtual */ uint GetId()
- {
- return (uint)m_thr;
- }
-
-private:
- /**
- * On thread creation, this function is called, which calls the real startup
- * function. This to get back into the correct instance again.
- */
- static void *stThreadProc(void *thr)
- {
- return ((ThreadObject_pthread*)thr)->ThreadProc();
- }
-
- /**
- * A new thread is created, and this function is called. Call the custom
- * function of the creator of the thread.
- */
- void *ThreadProc()
- {
- /* The new thread stops here so the calling thread can complete pthread_create() call */
- sem_wait(&m_sem_start);
-
- /* Call the proc of the creator to continue this thread */
- try {
- m_proc(m_param);
- } catch (...) {
- DEBUG(misc, 0, "Exception in thread %u!", GetId());
- }
- /* The thread died, so we are no longer valid */
- m_thr = 0;
-
- /* Notify threads waiting for our completion */
- sem_post(&m_sem_stop);
- return NULL;
- }
-};
-
-/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param)
-{
- return new ThreadObject_pthread(proc, param);
-}
-
-/* static */ ThreadObject *ThreadObject::AttachCurrent()
-{
- return new ThreadObject_pthread();
-}
-
-/* static */ uint ThreadObject::CurrentId()
-{
- return (uint)pthread_self();
-}
-
-
-/**
- * POSIX pthread version of ThreadSemaphore.
- */
-struct ThreadSemaphore_pthread : public ThreadSemaphore {
-private:
- sem_t m_sem;
-
-public:
- ThreadSemaphore_pthread()
- {
- sem_init(&m_sem, 0, 0);
- }
-
- /* virtual */ ~ThreadSemaphore_pthread()
- {
- sem_destroy(&m_sem);
- }
-
- /* virtual */ void Set()
- {
- int val = 0;
- if (sem_getvalue(&m_sem, &val) == 0 && val == 0) sem_post(&m_sem);
- }
-
- /* virtual */ void Wait()
- {
- sem_wait(&m_sem);
- }
-};
-
-/* static */ ThreadSemaphore *ThreadSemaphore::New()
-{
- return new ThreadSemaphore_pthread();
-}
-
-#elif defined(WIN32)
-
-#include <windows.h>
-#include <process.h>
-
-struct OTTDThread {
- HANDLE thread;
- uint thread_id;
- OTTDThreadFunc func;
- void *arg;
- void *ret;
-};
-
-static unsigned WINAPI Proxy(LPVOID arg)
-{
- OTTDThread *t = (OTTDThread *)arg;
- t->ret = t->func(t->arg);
- return 0;
-}
-
-OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
-{
- OTTDThread *t = MallocT<OTTDThread>(1);
-
- if (t == NULL) return NULL;
-
- t->func = function;
- t->arg = arg;
- t->thread = (HANDLE)_beginthreadex(NULL, 0, Proxy, t, 0, &t->thread_id);
-
- if (t->thread != NULL) {
- return t;
- } else {
- free(t);
- return NULL;
- }
-}
-
-void *OTTDJoinThread(OTTDThread *t)
-{
- void *ret;
-
- if (t == NULL) return NULL;
-
- WaitForSingleObject(t->thread, INFINITE);
- CloseHandle(t->thread);
- ret = t->ret;
- free(t);
- return ret;
-}
-
-void OTTDExitThread()
-{
- _endthreadex(0);
-}
-
-/**
- * Win32 thread version for ThreadObject.
- */
-struct ThreadObject_Win32 : public ThreadObject {
- uint m_id_thr;
- HANDLE m_h_thr;
- OTTDThreadFunc m_proc;
- void *m_param;
- bool m_attached;
-
- /**
- * Create a win32 thread and start it, calling proc(param).
- */
- ThreadObject_Win32(OTTDThreadFunc proc, void *param) :
- m_id_thr(0),
- m_h_thr(NULL),
- m_proc(proc),
- m_param(param),
- m_attached(false)
- {
- m_h_thr = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &m_id_thr);
- if (m_h_thr == NULL) return;
- ResumeThread(m_h_thr);
- }
-
- /**
- * Create a win32 thread and attach current thread to it.
- */
- ThreadObject_Win32() :
- m_id_thr(0),
- m_h_thr(NULL),
- m_proc(NULL),
- m_param(NULL),
- m_attached(false)
- {
- BOOL ret = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m_h_thr, 0, FALSE, DUPLICATE_SAME_ACCESS);
- if (!ret) return;
- m_id_thr = GetCurrentThreadId();
- }
-
- /* virtual */ ~ThreadObject_Win32()
- {
- if (m_h_thr != NULL) {
- CloseHandle(m_h_thr);
- m_h_thr = NULL;
- }
- }
-
- /* virtual */ bool IsRunning()
- {
- if (m_h_thr == NULL) return false;
- DWORD exit_code = 0;
- if (!GetExitCodeThread(m_h_thr, &exit_code)) return false;
- return (exit_code == STILL_ACTIVE);
- }
-
- /* virtual */ bool WaitForStop()
- {
- /* You can't wait on yourself */
- assert(!IsCurrent());
- /* If the thread is not running, waiting is over */
- if (!IsRunning()) return true;
-
- DWORD res = WaitForSingleObject(m_h_thr, INFINITE);
- return res == WAIT_OBJECT_0;
- }
-
- /* virtual */ bool IsCurrent()
- {
- DWORD id_cur = GetCurrentThreadId();
- return id_cur == m_id_thr;
- }
-
- /* virtual */ uint GetId()
- {
- return m_id_thr;
- }
-
-private:
- /**
- * On thread creation, this function is called, which calls the real startup
- * function. This to get back into the correct instance again.
- */
- static uint CALLBACK stThreadProc(void *thr)
- {
- return ((ThreadObject_Win32*)thr)->ThreadProc();
- }
-
- /**
- * A new thread is created, and this function is called. Call the custom
- * function of the creator of the thread.
- */
- uint ThreadProc()
- {
- try {
- m_proc(m_param);
- } catch (...) {
- DEBUG(misc, 0, "Exception in thread %d!", m_id_thr);
- }
-
- return 0;
- }
-};
-
-/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param)
-{
- return new ThreadObject_Win32(proc, param);
-}
-
-/* static */ ThreadObject* ThreadObject::AttachCurrent()
-{
- return new ThreadObject_Win32();
-}
-
-/* static */ uint ThreadObject::CurrentId()
-{
- return GetCurrentThreadId();
-}
-
-
-/**
- * Win32 thread version of ThreadSemaphore.
- */
-struct ThreadSemaphore_Win32 : public ThreadSemaphore {
-private:
- HANDLE m_handle;
-
-public:
- ThreadSemaphore_Win32()
- {
- m_handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
- }
-
- /* virtual */ ~ThreadSemaphore_Win32()
- {
- ::CloseHandle(m_handle);
- }
-
- /* virtual */ void Set()
- {
- ::SetEvent(m_handle);
- }
-
- /* virtual */ void Wait()
- {
- ::WaitForSingleObject(m_handle, INFINITE);
- }
-};
-
-/* static */ ThreadSemaphore *ThreadSemaphore::New()
-{
- return new ThreadSemaphore_Win32();
-}
-
-#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread_none.cpp Tue Apr 01 13:40:36 2008 +0000
@@ -0,0 +1,18 @@
+/* $Id$ */
+
+/** @file thread_none.cpp No-Threads-Available implementation of Threads */
+
+#include "stdafx.h"
+#include "thread.h"
+
+OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg) {
+ return NULL;
+}
+
+void *OTTDJoinThread(OTTDThread *t) {
+ return NULL;
+}
+
+void OTTDExitThread() {
+ NOT_REACHED();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread_os2.cpp Tue Apr 01 13:40:36 2008 +0000
@@ -0,0 +1,60 @@
+/* $Id$ */
+
+/** @file thread_os2.cpp OS2 implementation of Threads. */
+
+#include "stdafx.h"
+#include "thread.h"
+#include "debug.h"
+#include "core/alloc_func.hpp"
+#include <stdlib.h>
+
+#define INCL_DOS
+#include <os2.h>
+#include <process.h>
+
+struct OTTDThread {
+ TID thread;
+ OTTDThreadFunc func;
+ void *arg;
+ void *ret;
+};
+
+static void Proxy(void *arg)
+{
+ OTTDThread *t = (OTTDThread *)arg;
+ t->ret = t->func(t->arg);
+}
+
+OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
+{
+ OTTDThread *t = MallocT<OTTDThread>(1);
+
+ if (t == NULL) return NULL;
+
+ t->func = function;
+ t->arg = arg;
+ t->thread = _beginthread(Proxy, NULL, 32768, t);
+ if (t->thread != (TID)-1) {
+ return t;
+ } else {
+ free(t);
+ return NULL;
+ }
+}
+
+void *OTTDJoinThread(OTTDThread *t)
+{
+ void *ret;
+
+ if (t == NULL) return NULL;
+
+ DosWaitThread(&t->thread, DCWW_WAIT);
+ ret = t->ret;
+ free(t);
+ return ret;
+}
+
+void OTTDExitThread()
+{
+ _endthread();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread_pthread.cpp Tue Apr 01 13:40:36 2008 +0000
@@ -0,0 +1,213 @@
+/* $Id$ */
+
+/** @file thread_pthread.cpp POSIX pthread implementation of Threads. */
+
+#include "stdafx.h"
+#include "thread.h"
+#include "debug.h"
+#include "core/alloc_func.hpp"
+#include <stdlib.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>
+
+struct OTTDThread {
+ pthread_t thread;
+};
+
+OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
+{
+ OTTDThread *t = MallocT<OTTDThread>(1);
+
+ if (t == NULL) return NULL;
+
+ if (pthread_create(&t->thread, NULL, function, arg) == 0) {
+ return t;
+ } else {
+ free(t);
+ return NULL;
+ }
+}
+
+void *OTTDJoinThread(OTTDThread *t)
+{
+ void* ret;
+
+ if (t == NULL) return NULL;
+
+ pthread_join(t->thread, &ret);
+ free(t);
+ return ret;
+}
+
+void OTTDExitThread()
+{
+ pthread_exit(NULL);
+}
+
+
+/**
+ * POSIX pthread version for ThreadObject.
+ */
+class ThreadObject_pthread : public ThreadObject {
+private:
+ pthread_t m_thr; ///< System thread identifier.
+ OTTDThreadFunc m_proc; ///< External thread procedure.
+ void *m_param; ///< Parameter for the external thread procedure.
+ bool m_attached; ///< True if the ThreadObject was attached to an existing thread.
+ sem_t m_sem_start; ///< Here the new thread waits before it starts.
+ sem_t m_sem_stop; ///< Here the other thread can wait for this thread to end.
+
+public:
+ /**
+ * Create a pthread and start it, calling proc(param).
+ */
+ ThreadObject_pthread(OTTDThreadFunc proc, void *param) :
+ m_thr(0),
+ m_proc(proc),
+ m_param(param),
+ m_attached(false)
+ {
+ sem_init(&m_sem_start, 0, 0);
+ sem_init(&m_sem_stop, 0, 0);
+
+ pthread_create(&m_thr, NULL, &stThreadProc, this);
+ sem_post(&m_sem_start);
+ }
+
+ /**
+ * Create a pthread and attach current thread to it.
+ */
+ ThreadObject_pthread() :
+ m_thr(0),
+ m_proc(NULL),
+ m_param(0),
+ m_attached(true)
+ {
+ sem_init(&m_sem_start, 0, 0);
+ sem_init(&m_sem_stop, 0, 0);
+
+ m_thr = pthread_self();
+ }
+
+ /* virtual */ ~ThreadObject_pthread()
+ {
+ sem_destroy(&m_sem_stop);
+ sem_destroy(&m_sem_start);
+ };
+
+ /* virtual */ bool IsRunning()
+ {
+ return m_thr != 0;
+ }
+
+ /* virtual */ bool WaitForStop()
+ {
+ /* You can't wait on yourself */
+ assert(!IsCurrent());
+ /* If the thread is not running, waiting is over */
+ if (!IsRunning()) return true;
+
+ int ret = sem_wait(&m_sem_stop);
+ if (ret == 0) {
+ /* We have passed semaphore so increment it again */
+ sem_post(&m_sem_stop);
+ return true;
+ }
+ return false;
+ }
+
+ /* virtual */ bool IsCurrent()
+ {
+ return pthread_self() == m_thr;
+ }
+
+ /* virtual */ uint GetId()
+ {
+ return (uint)m_thr;
+ }
+
+private:
+ /**
+ * On thread creation, this function is called, which calls the real startup
+ * function. This to get back into the correct instance again.
+ */
+ static void *stThreadProc(void *thr)
+ {
+ return ((ThreadObject_pthread*)thr)->ThreadProc();
+ }
+
+ /**
+ * A new thread is created, and this function is called. Call the custom
+ * function of the creator of the thread.
+ */
+ void *ThreadProc()
+ {
+ /* The new thread stops here so the calling thread can complete pthread_create() call */
+ sem_wait(&m_sem_start);
+
+ /* Call the proc of the creator to continue this thread */
+ try {
+ m_proc(m_param);
+ } catch (...) {
+ DEBUG(misc, 0, "Exception in thread %u!", GetId());
+ }
+ /* The thread died, so we are no longer valid */
+ m_thr = 0;
+
+ /* Notify threads waiting for our completion */
+ sem_post(&m_sem_stop);
+ return NULL;
+ }
+};
+
+/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param)
+{
+ return new ThreadObject_pthread(proc, param);
+}
+
+/* static */ ThreadObject *ThreadObject::AttachCurrent()
+{
+ return new ThreadObject_pthread();
+}
+
+/* static */ uint ThreadObject::CurrentId()
+{
+ return (uint)pthread_self();
+}
+
+
+/**
+ * POSIX pthread version of ThreadSemaphore.
+ */
+class ThreadSemaphore_pthread : public ThreadSemaphore {
+private:
+ sem_t m_sem;
+
+public:
+ ThreadSemaphore_pthread()
+ {
+ sem_init(&m_sem, 0, 0);
+ }
+
+ /* virtual */ ~ThreadSemaphore_pthread()
+ {
+ sem_destroy(&m_sem);
+ }
+
+ /* virtual */ void Set()
+ {
+ int val = 0;
+ if (sem_getvalue(&m_sem, &val) == 0 && val == 0) sem_post(&m_sem);
+ }
+
+ /* virtual */ void Wait()
+ {
+ sem_wait(&m_sem);
+ }
+};
+
+/* static */ ThreadSemaphore *ThreadSemaphore::New()
+{
+ return new ThreadSemaphore_pthread();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread_win32.cpp Tue Apr 01 13:40:36 2008 +0000
@@ -0,0 +1,216 @@
+/* $Id$ */
+
+/** @file thread_win32.cpp Win32 thread implementation of Threads. */
+
+#include "stdafx.h"
+#include "thread.h"
+#include "debug.h"
+#include "core/alloc_func.hpp"
+#include <stdlib.h>
+#include <windows.h>
+#include <process.h>
+
+struct OTTDThread {
+ HANDLE thread;
+ uint thread_id;
+ OTTDThreadFunc func;
+ void *arg;
+ void *ret;
+};
+
+static unsigned WINAPI Proxy(LPVOID arg)
+{
+ OTTDThread *t = (OTTDThread *)arg;
+ t->ret = t->func(t->arg);
+ return 0;
+}
+
+OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
+{
+ OTTDThread *t = MallocT<OTTDThread>(1);
+
+ if (t == NULL) return NULL;
+
+ t->func = function;
+ t->arg = arg;
+ t->thread = (HANDLE)_beginthreadex(NULL, 0, Proxy, t, 0, &t->thread_id);
+
+ if (t->thread != NULL) {
+ return t;
+ } else {
+ free(t);
+ return NULL;
+ }
+}
+
+void *OTTDJoinThread(OTTDThread *t)
+{
+ void *ret;
+
+ if (t == NULL) return NULL;
+
+ WaitForSingleObject(t->thread, INFINITE);
+ CloseHandle(t->thread);
+ ret = t->ret;
+ free(t);
+ return ret;
+}
+
+void OTTDExitThread()
+{
+ _endthreadex(0);
+}
+
+/**
+ * Win32 thread version for ThreadObject.
+ */
+class ThreadObject_Win32 : public ThreadObject {
+ uint m_id_thr;
+ HANDLE m_h_thr;
+ OTTDThreadFunc m_proc;
+ void *m_param;
+ bool m_attached;
+
+ /**
+ * Create a win32 thread and start it, calling proc(param).
+ */
+ ThreadObject_Win32(OTTDThreadFunc proc, void *param) :
+ m_id_thr(0),
+ m_h_thr(NULL),
+ m_proc(proc),
+ m_param(param),
+ m_attached(false)
+ {
+ m_h_thr = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &m_id_thr);
+ if (m_h_thr == NULL) return;
+ ResumeThread(m_h_thr);
+ }
+
+ /**
+ * Create a win32 thread and attach current thread to it.
+ */
+ ThreadObject_Win32() :
+ m_id_thr(0),
+ m_h_thr(NULL),
+ m_proc(NULL),
+ m_param(NULL),
+ m_attached(false)
+ {
+ BOOL ret = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m_h_thr, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if (!ret) return;
+ m_id_thr = GetCurrentThreadId();
+ }
+
+ /* virtual */ ~ThreadObject_Win32()
+ {
+ if (m_h_thr != NULL) {
+ CloseHandle(m_h_thr);
+ m_h_thr = NULL;
+ }
+ }
+
+ /* virtual */ bool IsRunning()
+ {
+ if (m_h_thr == NULL) return false;
+ DWORD exit_code = 0;
+ if (!GetExitCodeThread(m_h_thr, &exit_code)) return false;
+ return (exit_code == STILL_ACTIVE);
+ }
+
+ /* virtual */ bool WaitForStop()
+ {
+ /* You can't wait on yourself */
+ assert(!IsCurrent());
+ /* If the thread is not running, waiting is over */
+ if (!IsRunning()) return true;
+
+ DWORD res = WaitForSingleObject(m_h_thr, INFINITE);
+ return res == WAIT_OBJECT_0;
+ }
+
+ /* virtual */ bool IsCurrent()
+ {
+ DWORD id_cur = GetCurrentThreadId();
+ return id_cur == m_id_thr;
+ }
+
+ /* virtual */ uint GetId()
+ {
+ return m_id_thr;
+ }
+
+private:
+ /**
+ * On thread creation, this function is called, which calls the real startup
+ * function. This to get back into the correct instance again.
+ */
+ static uint CALLBACK stThreadProc(void *thr)
+ {
+ return ((ThreadObject_Win32*)thr)->ThreadProc();
+ }
+
+ /**
+ * A new thread is created, and this function is called. Call the custom
+ * function of the creator of the thread.
+ */
+ uint ThreadProc()
+ {
+ try {
+ m_proc(m_param);
+ } catch (...) {
+ DEBUG(misc, 0, "Exception in thread %d!", m_id_thr);
+ }
+
+ return 0;
+ }
+};
+
+/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param)
+{
+ return new ThreadObject_Win32(proc, param);
+}
+
+/* static */ ThreadObject* ThreadObject::AttachCurrent()
+{
+ return new ThreadObject_Win32();
+}
+
+/* static */ uint ThreadObject::CurrentId()
+{
+ return GetCurrentThreadId();
+}
+
+
+/**
+ * Win32 thread version of ThreadSemaphore.
+ */
+class ThreadSemaphore_Win32 : public ThreadSemaphore {
+private:
+ HANDLE m_handle;
+
+public:
+ ThreadSemaphore_Win32()
+ {
+ m_handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ }
+
+ /* virtual */ ~ThreadSemaphore_Win32()
+ {
+ ::CloseHandle(m_handle);
+ }
+
+ /* virtual */ void Set()
+ {
+ ::SetEvent(m_handle);
+ }
+
+ /* virtual */ void Wait()
+ {
+ ::WaitForSingleObject(m_handle, INFINITE);
+ }
+};
+
+/* static */ ThreadSemaphore *ThreadSemaphore::New()
+{
+ return new ThreadSemaphore_Win32();
+}