(svn r2809) Implement more generic threading functions, which allow more than one thread
authortron
Fri, 05 Aug 2005 09:15:41 +0000
changeset 2285 3193cbd1ba88
parent 2284 552f3dddd93a
child 2286 acb76b379e72
(svn r2809) Implement more generic threading functions, which allow more than one thread
Makefile
functions.h
openttd.c
openttd.tgt
os2.c
saveload.c
saveload.h
thread.c
thread.h
unix.c
win32.c
--- a/Makefile	Fri Aug 05 08:31:29 2005 +0000
+++ b/Makefile	Fri Aug 05 09:15:41 2005 +0000
@@ -665,6 +665,7 @@
 C_SOURCES += subsidy_gui.c
 C_SOURCES += terraform_gui.c
 C_SOURCES += texteff.c
+C_SOURCES += thread.c
 C_SOURCES += tile.c
 C_SOURCES += town_cmd.c
 C_SOURCES += town_gui.c
--- a/functions.h	Fri Aug 05 08:31:29 2005 +0000
+++ b/functions.h	Fri Aug 05 09:15:41 2005 +0000
@@ -278,6 +278,4 @@
 void DeterminePaths(void);
 
 void bubblesort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
-bool CreateOTTDThread(void *func, void *param);
-void JoinOTTDThread(void);
 #endif /* FUNCTIONS_H */
--- a/openttd.c	Fri Aug 05 08:31:29 2005 +0000
+++ b/openttd.c	Fri Aug 05 09:15:41 2005 +0000
@@ -507,7 +507,7 @@
 
 	_video_driver->main_loop();
 
-	JoinOTTDThread();
+	WaitTillSaved();
 	IConsoleFree();
 
 #ifdef ENABLE_NETWORK
--- a/openttd.tgt	Fri Aug 05 08:31:29 2005 +0000
+++ b/openttd.tgt	Fri Aug 05 09:15:41 2005 +0000
@@ -194,7 +194,7 @@
 0
 51
 WPickList
-115
+116
 52
 MItem
 3
@@ -2148,8 +2148,8 @@
 0
 492
 MItem
-6
-tile.c
+8
+thread.c
 493
 WString
 4
@@ -2166,8 +2166,8 @@
 0
 496
 MItem
-10
-town_cmd.c
+6
+tile.c
 497
 WString
 4
@@ -2185,7 +2185,7 @@
 500
 MItem
 10
-town_gui.c
+town_cmd.c
 501
 WString
 4
@@ -2202,8 +2202,8 @@
 0
 504
 MItem
-11
-train_cmd.c
+10
+town_gui.c
 505
 WString
 4
@@ -2221,7 +2221,7 @@
 508
 MItem
 11
-train_gui.c
+train_cmd.c
 509
 WString
 4
@@ -2238,8 +2238,8 @@
 0
 512
 MItem
-10
-tree_cmd.c
+11
+train_gui.c
 513
 WString
 4
@@ -2256,8 +2256,8 @@
 0
 516
 MItem
-18
-tunnelbridge_cmd.c
+10
+tree_cmd.c
 517
 WString
 4
@@ -2274,8 +2274,8 @@
 0
 520
 MItem
-15
-unmovable_cmd.c
+18
+tunnelbridge_cmd.c
 521
 WString
 4
@@ -2292,8 +2292,8 @@
 0
 524
 MItem
-9
-vehicle.c
+15
+unmovable_cmd.c
 525
 WString
 4
@@ -2310,8 +2310,8 @@
 0
 528
 MItem
-13
-vehicle_gui.c
+9
+vehicle.c
 529
 WString
 4
@@ -2328,8 +2328,8 @@
 0
 532
 MItem
-19
-video\dedicated_v.c
+13
+vehicle_gui.c
 533
 WString
 4
@@ -2346,8 +2346,8 @@
 0
 536
 MItem
-14
-video\null_v.c
+19
+video\dedicated_v.c
 537
 WString
 4
@@ -2364,8 +2364,8 @@
 0
 540
 MItem
-13
-video\sdl_v.c
+14
+video\null_v.c
 541
 WString
 4
@@ -2382,8 +2382,8 @@
 0
 544
 MItem
-10
-viewport.c
+13
+video\sdl_v.c
 545
 WString
 4
@@ -2400,8 +2400,8 @@
 0
 548
 MItem
-11
-water_cmd.c
+10
+viewport.c
 549
 WString
 4
@@ -2418,8 +2418,8 @@
 0
 552
 MItem
-10
-waypoint.c
+11
+water_cmd.c
 553
 WString
 4
@@ -2436,8 +2436,8 @@
 0
 556
 MItem
-8
-widget.c
+10
+waypoint.c
 557
 WString
 4
@@ -2455,7 +2455,7 @@
 560
 MItem
 8
-window.c
+widget.c
 561
 WString
 4
@@ -2470,3 +2470,21 @@
 1
 1
 0
+564
+MItem
+8
+window.c
+565
+WString
+4
+COBJ
+566
+WVList
+0
+567
+WVList
+0
+52
+1
+1
+0
--- a/os2.c	Fri Aug 05 08:31:29 2005 +0000
+++ b/os2.c	Fri Aug 05 09:15:41 2005 +0000
@@ -15,11 +15,9 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <stdlib.h>
-#include <process.h>
 #include <time.h>
 #include <dos.h>
 
-#define INCL_DOS
 #define INCL_WIN
 #define INCL_WINCLIPBOARD
 
@@ -632,28 +630,6 @@
 	return false;
 }
 
-static TID thread1 = 0;
-
-// The thread function must be declared and compiled using _Optlink linkage, apparently
-// It seems to work, though :)
-
-bool CreateOTTDThread(void *func, void *param)
-{
-	thread1 = _beginthread(func, NULL, 32768, param);
-
-	if (thread1 == -1)
-		return(false);
-
-	return(true);
-}
-
-void JoinOTTDThread(void)
-{
-	if (thread1 == 0)
-		return;
-
-	DosWaitThread(&thread1, DCWW_WAIT);
-}
 
 void CSleep(int milliseconds)
 {
--- a/saveload.c	Fri Aug 05 08:31:29 2005 +0000
+++ b/saveload.c	Fri Aug 05 09:15:41 2005 +0000
@@ -21,6 +21,7 @@
 #include "functions.h"
 #include "vehicle.h"
 #include "station.h"
+#include "thread.h"
 #include "town.h"
 #include "player.h"
 #include "saveload.h"
@@ -1234,7 +1235,7 @@
 /** We have written the whole game into memory, _save_pool, now find
  * and appropiate compressor and start writing to file.
  */
-static bool SaveFileToDisk(void *ptr)
+static void SaveFileToDisk(void* arg)
 {
 	const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format);
 	/* XXX - backup _sl.buf cause it is used internally by the writer
@@ -1257,7 +1258,7 @@
 		ShowErrorMessage(STR_4007_GAME_SAVE_FAILED, STR_NULL, 0, 0);
 
 		SaveFileDone();
-		return false;
+		return;
 	}
 
 	/* We have written our stuff to memory, now write it to file! */
@@ -1292,9 +1293,18 @@
 	fclose(_sl.fh);
 
 	SaveFileDone();
-	return true;
 }
 
+
+static Thread* save_thread;
+
+void WaitTillSaved(void)
+{
+	OTTDJoinThread(save_thread);
+	save_thread = NULL;
+}
+
+
 /**
  * Main Save or Load function where the high-level saveload functions are
  * handled. It opens the savegame, selects format and checks versions
@@ -1311,7 +1321,7 @@
 	/* An instance of saving is already active, so wait until it is done */
 	if (_ts.saveinprogress) {
 		if (!_do_autosave) ShowErrorMessage(_error_message, STR_SAVE_STILL_IN_PROGRESS, 0, 0);
-		JoinOTTDThread(); // synchronize and wait until save is finished to continue
+		WaitTillSaved();
 		// nonsense to do an autosave while we were still saving our game, so skip it
 		if (_do_autosave) return SL_OK;
 	}
@@ -1379,7 +1389,8 @@
 		SlWriteFill(); // flush the save buffer
 
 		/* Write to file */
-		if (_network_server || !CreateOTTDThread(&SaveFileToDisk, NULL)) {
+		if (_network_server ||
+				(save_thread = OTTDCreateThread(&SaveFileToDisk, NULL)) == NULL) {
 			DEBUG(misc, 1) ("cannot create savegame thread, reverting to single-threaded mode...");
 			SaveFileToDisk(NULL);
 		}
--- a/saveload.h	Fri Aug 05 08:31:29 2005 +0000
+++ b/saveload.h	Fri Aug 05 09:15:41 2005 +0000
@@ -19,6 +19,7 @@
 } SaveOrLoadMode;
 
 SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
+void WaitTillSaved(void);
 
 
 typedef void ChunkSaveLoadProc(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread.c	Fri Aug 05 09:15:41 2005 +0000
@@ -0,0 +1,112 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "thread.h"
+#include <stdlib.h>
+
+#if defined(__AMIGA__) || defined(__MORPHOS__)
+Thread* OTTDCreateThread(ThreadFunc function, void* arg) { return NULL; }
+void OTTDJoinThread(Thread*) {}
+
+
+#elif defined(__OS2__)
+
+#define INCL_DOS
+#include <os2.h>
+#include <process.h>
+
+struct Thread {
+	TID thread;
+};
+
+Thread* OTTDCreateThread(ThreadFunc function, void* arg)
+{
+	Thread* t = malloc(sizeof(*t));
+
+	if (t == NULL) return NULL;
+
+	t->thread = _beginthread(function, NULL, 32768, arg);
+	if (t->thread != -1) {
+		return t;
+	} else {
+		free(t);
+		return NULL;
+	}
+}
+
+void OTTDJoinThread(Thread* t)
+{
+	if (t == NULL) return;
+
+	DosWaitThread(&t->thread, DCWW_WAIT);
+	free(t);
+}
+
+
+#elif defined(UNIX)
+
+#include <pthread.h>
+
+struct Thread {
+	pthread_t thread;
+};
+
+Thread* OTTDCreateThread(ThreadFunc function, void* arg)
+{
+	Thread* t = malloc(sizeof(*t));
+
+	if (t == NULL) return NULL;
+
+	if (pthread_create(&t->thread, NULL, (void* (*)(void*))function, arg) == 0) {
+		return t;
+	} else {
+		free(t);
+		return NULL;
+	}
+}
+
+void OTTDJoinThread(Thread* t)
+{
+	if (t == NULL) return;
+
+	pthread_join(t->thread, NULL);
+	free(t);
+}
+
+
+#elif defined(WIN32)
+
+#include <windows.h>
+
+struct Thread {
+	HANDLE thread;
+};
+
+Thread* OTTDCreateThread(ThreadFunc function, void* arg)
+{
+	Thread* t = malloc(sizeof(*t));
+	DWORD dwThreadId;
+
+	if (t == NULL) return NULL;
+
+	t->thread = CreateThread(
+		NULL, 0, (LPTHREAD_START_ROUTINE)function, arg, 0, &dwThreadId
+	);
+
+	if (t->thread != NULL) {
+		return t;
+	} else {
+		free(t);
+		return NULL;
+	}
+}
+
+void OTTDJoinThread(Thread* t)
+{
+	if (t == NULL) return;
+
+	WaitForSingleObject(t->thread, INFINITE);
+	CloseHandle(t->thread);
+	free(t);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread.h	Fri Aug 05 09:15:41 2005 +0000
@@ -0,0 +1,19 @@
+/* $Id$ */
+
+#ifndef THREAD_H
+#define THREAD_H
+
+/*
+ * DO NOT USE THREADS if you don't know what race conditions, mutexes,
+ * semaphores, atomic operations, etc. are or how to properly handle them.
+ * Ask somebody who has a clue.
+ */
+
+typedef struct Thread Thread;
+
+typedef void (*ThreadFunc)(void*);
+
+Thread* OTTDCreateThread(ThreadFunc, void*);
+void    OTTDJoinThread(Thread*);
+
+#endif
--- a/unix.c	Fri Aug 05 08:31:29 2005 +0000
+++ b/unix.c	Fri Aug 05 09:15:41 2005 +0000
@@ -14,9 +14,6 @@
 #include <sys/stat.h>
 #include <time.h>
 #include <signal.h>
-#if !defined(__MORPHOS__) && !defined(__AMIGA__)
- #include <pthread.h>
-#endif
 
 #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
 	#define HAS_STATVFS
@@ -515,29 +512,6 @@
 	return false;
 }
 
-/** Dummy stubs as MorphOS/ AmigaOS does not really
- *  know about a thread concept nor has a working libpthread */
-#if defined(__MORPHOS__) || defined(__AMIGA__)
- typedef int pthread_t;
- #define pthread_create(thread, attr, function, arg) (true)
- #define pthread_join(thread, retval)
-#endif
-
-static pthread_t thread1 = 0;
-
-bool CreateOTTDThread(void *func, void *param)
-{
-	return pthread_create(&thread1, NULL, func, param) == 0;
-}
-
-void JoinOTTDThread(void)
-{
-	if (thread1 == 0) return;
-
-	pthread_join(thread1, NULL);
-}
-
-
 
 #ifdef ENABLE_NETWORK
 
--- a/win32.c	Fri Aug 05 08:31:29 2005 +0000
+++ b/win32.c	Fri Aug 05 09:15:41 2005 +0000
@@ -1193,25 +1193,6 @@
 	return false;
 }
 
-static HANDLE hThread;
-
-bool CreateOTTDThread(void *func, void *param)
-{
-	DWORD dwThreadId;
-	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, param, 0, &dwThreadId);
-	SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
-
-	return hThread != NULL;
-}
-
-void JoinOTTDThread(void)
-{
-	if (hThread == NULL) return;
-
-	WaitForSingleObject(hThread, INFINITE);
-	if (!CloseHandle(hThread)) DEBUG(misc, 0) ("Failed to close thread handle!");
-}
-
 
 void CSleep(int milliseconds)
 {