(svn r2809) Implement more generic threading functions, which allow more than one thread

This commit is contained in:
tron 2005-08-05 09:15:41 +00:00
parent 4f9b0d5f29
commit 4696ef802a
11 changed files with 202 additions and 111 deletions

View File

@ -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

View File

@ -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 */

View File

@ -507,7 +507,7 @@ int ttd_main(int argc, char* argv[])
_video_driver->main_loop();
JoinOTTDThread();
WaitTillSaved();
IConsoleFree();
#ifdef ENABLE_NETWORK

View File

@ -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
View File

@ -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)
{

View File

@ -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);
}

View File

@ -19,6 +19,7 @@ typedef enum SaveOrLoadMode {
} SaveOrLoadMode;
SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
void WaitTillSaved(void);
typedef void ChunkSaveLoadProc(void);

112
thread.c Normal file
View File

@ -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

19
thread.h Normal file
View File

@ -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
View File

@ -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
View File

@ -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)
{