summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortron <tron@openttd.org>2005-08-05 09:15:41 +0000
committertron <tron@openttd.org>2005-08-05 09:15:41 +0000
commitf315c95fa1221441106f1e6e4f4a0f7849ccb4b4 (patch)
tree4db884818a15ec2dc30fe1f1e660bded27872dae
parent69f79c9f4988c5fdb7308566e3bf56e0fe8b0594 (diff)
downloadopenttd-f315c95fa1221441106f1e6e4f4a0f7849ccb4b4.tar.xz
(svn r2809) Implement more generic threading functions, which allow more than one thread
-rw-r--r--Makefile1
-rw-r--r--functions.h2
-rw-r--r--openttd.c2
-rw-r--r--openttd.tgt86
-rw-r--r--os2.c24
-rw-r--r--saveload.c21
-rw-r--r--saveload.h1
-rw-r--r--thread.c112
-rw-r--r--thread.h19
-rw-r--r--unix.c26
-rw-r--r--win32.c19
11 files changed, 202 insertions, 111 deletions
diff --git a/Makefile b/Makefile
index ddccf0376..49a52f2da 100644
--- a/Makefile
+++ b/Makefile
@@ -665,6 +665,7 @@ C_SOURCES += strings.c
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
diff --git a/functions.h b/functions.h
index 8537e6e13..f0763acb9 100644
--- a/functions.h
+++ b/functions.h
@@ -278,6 +278,4 @@ int ttd_main(int argc, char* argv[]);
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 */
diff --git a/openttd.c b/openttd.c
index 15262f8e4..f5659562b 100644
--- a/openttd.c
+++ b/openttd.c
@@ -507,7 +507,7 @@ int ttd_main(int argc, char* argv[])
_video_driver->main_loop();
- JoinOTTDThread();
+ WaitTillSaved();
IConsoleFree();
#ifdef ENABLE_NETWORK
diff --git a/openttd.tgt b/openttd.tgt
index ce652c8d2..bd5efa120 100644
--- a/openttd.tgt
+++ b/openttd.tgt
@@ -194,7 +194,7 @@ WVList
0
51
WPickList
-115
+116
52
MItem
3
@@ -2148,8 +2148,8 @@ WVList
0
492
MItem
-6
-tile.c
+8
+thread.c
493
WString
4
@@ -2166,8 +2166,8 @@ WVList
0
496
MItem
-10
-town_cmd.c
+6
+tile.c
497
WString
4
@@ -2185,7 +2185,7 @@ WVList
500
MItem
10
-town_gui.c
+town_cmd.c
501
WString
4
@@ -2202,8 +2202,8 @@ WVList
0
504
MItem
-11
-train_cmd.c
+10
+town_gui.c
505
WString
4
@@ -2221,7 +2221,7 @@ WVList
508
MItem
11
-train_gui.c
+train_cmd.c
509
WString
4
@@ -2238,8 +2238,8 @@ WVList
0
512
MItem
-10
-tree_cmd.c
+11
+train_gui.c
513
WString
4
@@ -2256,8 +2256,8 @@ WVList
0
516
MItem
-18
-tunnelbridge_cmd.c
+10
+tree_cmd.c
517
WString
4
@@ -2274,8 +2274,8 @@ WVList
0
520
MItem
-15
-unmovable_cmd.c
+18
+tunnelbridge_cmd.c
521
WString
4
@@ -2292,8 +2292,8 @@ WVList
0
524
MItem
-9
-vehicle.c
+15
+unmovable_cmd.c
525
WString
4
@@ -2310,8 +2310,8 @@ WVList
0
528
MItem
-13
-vehicle_gui.c
+9
+vehicle.c
529
WString
4
@@ -2328,8 +2328,8 @@ WVList
0
532
MItem
-19
-video\dedicated_v.c
+13
+vehicle_gui.c
533
WString
4
@@ -2346,8 +2346,8 @@ WVList
0
536
MItem
-14
-video\null_v.c
+19
+video\dedicated_v.c
537
WString
4
@@ -2364,8 +2364,8 @@ WVList
0
540
MItem
-13
-video\sdl_v.c
+14
+video\null_v.c
541
WString
4
@@ -2382,8 +2382,8 @@ WVList
0
544
MItem
-10
-viewport.c
+13
+video\sdl_v.c
545
WString
4
@@ -2400,8 +2400,8 @@ WVList
0
548
MItem
-11
-water_cmd.c
+10
+viewport.c
549
WString
4
@@ -2418,8 +2418,8 @@ WVList
0
552
MItem
-10
-waypoint.c
+11
+water_cmd.c
553
WString
4
@@ -2436,8 +2436,8 @@ WVList
0
556
MItem
-8
-widget.c
+10
+waypoint.c
557
WString
4
@@ -2455,7 +2455,7 @@ WVList
560
MItem
8
-window.c
+widget.c
561
WString
4
@@ -2470,3 +2470,21 @@ WVList
1
1
0
+564
+MItem
+8
+window.c
+565
+WString
+4
+COBJ
+566
+WVList
+0
+567
+WVList
+0
+52
+1
+1
+0
diff --git a/os2.c b/os2.c
index 468c01c55..8fe85b033 100644
--- a/os2.c
+++ b/os2.c
@@ -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 @@ bool InsertTextBufferClipboard(Textbuf *tb)
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)
{
diff --git a/saveload.c b/saveload.c
index e036ae748..0c33d8c83 100644
--- a/saveload.c
+++ b/saveload.c
@@ -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 @@ static inline void SaveFileDone(void)
/** 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 @@ static bool SaveFileToDisk(void *ptr)
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 @@ static bool SaveFileToDisk(void *ptr)
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 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode)
/* 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 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode)
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);
}
diff --git a/saveload.h b/saveload.h
index 852626982..9f3c65d06 100644
--- a/saveload.h
+++ b/saveload.h
@@ -19,6 +19,7 @@ typedef enum SaveOrLoadMode {
} SaveOrLoadMode;
SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
+void WaitTillSaved(void);
typedef void ChunkSaveLoadProc(void);
diff --git a/thread.c b/thread.c
new file mode 100644
index 000000000..6c70ebdb2
--- /dev/null
+++ b/thread.c
@@ -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
diff --git a/thread.h b/thread.h
new file mode 100644
index 000000000..1f4878106
--- /dev/null
+++ b/thread.h
@@ -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
diff --git a/unix.c b/unix.c
index cb13eb06d..ba2f6a922 100644
--- a/unix.c
+++ b/unix.c
@@ -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 @@ bool InsertTextBufferClipboard(Textbuf *tb)
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
diff --git a/win32.c b/win32.c
index f4857a075..0c31e61c6 100644
--- a/win32.c
+++ b/win32.c
@@ -1193,25 +1193,6 @@ bool InsertTextBufferClipboard(Textbuf *tb)
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)
{