changeset 11393:53442463c7c8 draft

(svn r15746) -Fix: Update threading code for OS/2, add mutex support
author orudge <orudge@openttd.org>
date Mon, 16 Mar 2009 20:05:24 +0000
parents 22ae657143b3
children c9c6f23ea1ac
files src/thread_os2.cpp
diffstat 1 files changed, 95 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/thread_os2.cpp
+++ b/src/thread_os2.cpp
@@ -1,66 +1,116 @@
 /* $Id$ */
 
-/** @file thread_os2.cpp OS2 implementation of Threads. */
+/** @file thread_os2.cpp OS/2 implementation of Threads. */
 
 #include "stdafx.h"
 #include "thread.h"
 
-#if 0
-#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;
+/**
+ * OS/2 version for ThreadObject.
+ */
+class ThreadObject_OS2 : public ThreadObject {
+private:
+	TID thread;          ///< System thread identifier.
+	OTTDThreadFunc proc; ///< External thread procedure.
+	void *param;         ///< Parameter for the external thread procedure.
+	bool self_destruct;  ///< Free ourselves when done?
+
+public:
+	/**
+	 * Create a thread and start it, calling proc(param).
+	 */
+	ThreadObject_OS2(OTTDThreadFunc proc, void *param, bool self_destruct) :
+		thread(0),
+		proc(proc),
+		param(param),
+		self_destruct(self_destruct)
+	{
+		thread = _beginthread(stThreadProc, NULL, 32768, this);
+	}
+
+	/* virtual */ bool Exit()
+	{
+		_endthread();
+		return true;
+	}
+
+	/* virtual */ void Join()
+	{
+		DosWaitThread(&this->thread, DCWW_WAIT);
+		this->thread = 0;
+	}
+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)
+	{
+		((ThreadObject_OS2 *)thr)->ThreadProc();
+	}
+
+	/**
+	 * A new thread is created, and this function is called. Call the custom
+	 *  function of the creator of the thread.
+	 */
+	void ThreadProc()
+	{
+		/* Call the proc of the creator to continue this thread */
+		try {
+			this->proc(this->param);
+		} catch (OTTDThreadExitSignal e) {
+		} catch (...) {
+			NOT_REACHED();
+		}
+
+		if (self_destruct) {
+			this->Exit();
+			delete this;
+		}
+	}
 };
 
-static void Proxy(void *arg)
+/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
 {
-	OTTDThread *t = (OTTDThread *)arg;
-	t->ret = t->func(t->arg);
+	ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL);
+	if (thread != NULL) *thread = to;
+	return true;
 }
 
-OTTDThread *OTTDCreateThread(OTTDThreadFunc function, void *arg)
-{
-	OTTDThread *t = MallocT<OTTDThread>(1);
+/**
+ * OS/2 version of ThreadMutex.
+ */
+class ThreadMutex_OS2 : public ThreadMutex {
+private:
+	HMTX mutex;
 
-	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;
+public:
+	ThreadMutex_OS2()
+	{
+		DosCreateMutexSem(NULL, &mutex, 0, FALSE);
 	}
-}
-
-void *OTTDJoinThread(OTTDThread *t)
-{
-	if (t == NULL) return NULL;
 
-	DosWaitThread(&t->thread, DCWW_WAIT);
-	void *ret = t->ret;
-	free(t);
-	return ret;
-}
+	/* virtual */ ~ThreadMutex_OS2()
+	{
+		DosCloseMutexSem(mutex);
+	}
 
-void OTTDExitThread()
+	/* virtual */ void BeginCritical()
+	{
+		DosRequestMutexSem(mutex, (unsigned long) SEM_INDEFINITE_WAIT);
+	}
+
+	/* virtual */ void EndCritical()
+	{
+		DosReleaseMutexSem(mutex);
+	}
+};
+
+/* static */ ThreadMutex *ThreadMutex::New()
 {
-	_endthread();
+	return new ThreadMutex_OS2();
 }
-
-#endif
-
-/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
-{
-	if (thread != NULL) *thread = NULL;
-	return false;
-}