mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r2809) Implement more generic threading functions, which allow more than one thread
This commit is contained in:
parent
4f9b0d5f29
commit
4696ef802a
1
Makefile
1
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -507,7 +507,7 @@ int ttd_main(int argc, char* argv[])
|
|||
|
||||
_video_driver->main_loop();
|
||||
|
||||
JoinOTTDThread();
|
||||
WaitTillSaved();
|
||||
IConsoleFree();
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
|
|
86
openttd.tgt
86
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
|
||||
|
|
24
os2.c
24
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)
|
||||
{
|
||||
|
|
21
saveload.c
21
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);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ typedef enum SaveOrLoadMode {
|
|||
} SaveOrLoadMode;
|
||||
|
||||
SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
|
||||
void WaitTillSaved(void);
|
||||
|
||||
|
||||
typedef void ChunkSaveLoadProc(void);
|
||||
|
|
|
@ -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
|
|
@ -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
|
26
unix.c
26
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
|
||||
|
||||
|
|
19
win32.c
19
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue