From f315c95fa1221441106f1e6e4f4a0f7849ccb4b4 Mon Sep 17 00:00:00 2001 From: tron Date: Fri, 5 Aug 2005 09:15:41 +0000 Subject: (svn r2809) Implement more generic threading functions, which allow more than one thread --- Makefile | 1 + functions.h | 2 -- openttd.c | 2 +- openttd.tgt | 86 ++++++++++++++++++++++++++++------------------ os2.c | 24 ------------- saveload.c | 21 +++++++++--- saveload.h | 1 + thread.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ thread.h | 19 +++++++++++ unix.c | 26 -------------- win32.c | 19 ----------- 11 files changed, 202 insertions(+), 111 deletions(-) create mode 100644 thread.c create mode 100644 thread.h 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 #include #include -#include #include #include -#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 + +#if defined(__AMIGA__) || defined(__MORPHOS__) +Thread* OTTDCreateThread(ThreadFunc function, void* arg) { return NULL; } +void OTTDJoinThread(Thread*) {} + + +#elif defined(__OS2__) + +#define INCL_DOS +#include +#include + +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 + +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 + +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 #include #include -#if !defined(__MORPHOS__) && !defined(__AMIGA__) - #include -#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) { -- cgit v1.2.3-54-g00ecf