mirror of https://github.com/OpenTTD/OpenTTD
(svn r2809) Implement more generic threading functions, which allow more than one thread
parent
4f9b0d5f29
commit
4696ef802a
1
Makefile
1
Makefile
|
@ -665,6 +665,7 @@ C_SOURCES += strings.c
|
||||||
C_SOURCES += subsidy_gui.c
|
C_SOURCES += subsidy_gui.c
|
||||||
C_SOURCES += terraform_gui.c
|
C_SOURCES += terraform_gui.c
|
||||||
C_SOURCES += texteff.c
|
C_SOURCES += texteff.c
|
||||||
|
C_SOURCES += thread.c
|
||||||
C_SOURCES += tile.c
|
C_SOURCES += tile.c
|
||||||
C_SOURCES += town_cmd.c
|
C_SOURCES += town_cmd.c
|
||||||
C_SOURCES += town_gui.c
|
C_SOURCES += town_gui.c
|
||||||
|
|
|
@ -278,6 +278,4 @@ int ttd_main(int argc, char* argv[]);
|
||||||
void DeterminePaths(void);
|
void DeterminePaths(void);
|
||||||
|
|
||||||
void bubblesort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const 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 */
|
#endif /* FUNCTIONS_H */
|
||||||
|
|
|
@ -507,7 +507,7 @@ int ttd_main(int argc, char* argv[])
|
||||||
|
|
||||||
_video_driver->main_loop();
|
_video_driver->main_loop();
|
||||||
|
|
||||||
JoinOTTDThread();
|
WaitTillSaved();
|
||||||
IConsoleFree();
|
IConsoleFree();
|
||||||
|
|
||||||
#ifdef ENABLE_NETWORK
|
#ifdef ENABLE_NETWORK
|
||||||
|
|
86
openttd.tgt
86
openttd.tgt
|
@ -194,7 +194,7 @@ WVList
|
||||||
0
|
0
|
||||||
51
|
51
|
||||||
WPickList
|
WPickList
|
||||||
115
|
116
|
||||||
52
|
52
|
||||||
MItem
|
MItem
|
||||||
3
|
3
|
||||||
|
@ -2148,8 +2148,8 @@ WVList
|
||||||
0
|
0
|
||||||
492
|
492
|
||||||
MItem
|
MItem
|
||||||
6
|
8
|
||||||
tile.c
|
thread.c
|
||||||
493
|
493
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2166,8 +2166,8 @@ WVList
|
||||||
0
|
0
|
||||||
496
|
496
|
||||||
MItem
|
MItem
|
||||||
10
|
6
|
||||||
town_cmd.c
|
tile.c
|
||||||
497
|
497
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2185,7 +2185,7 @@ WVList
|
||||||
500
|
500
|
||||||
MItem
|
MItem
|
||||||
10
|
10
|
||||||
town_gui.c
|
town_cmd.c
|
||||||
501
|
501
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2202,8 +2202,8 @@ WVList
|
||||||
0
|
0
|
||||||
504
|
504
|
||||||
MItem
|
MItem
|
||||||
11
|
10
|
||||||
train_cmd.c
|
town_gui.c
|
||||||
505
|
505
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2221,7 +2221,7 @@ WVList
|
||||||
508
|
508
|
||||||
MItem
|
MItem
|
||||||
11
|
11
|
||||||
train_gui.c
|
train_cmd.c
|
||||||
509
|
509
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2238,8 +2238,8 @@ WVList
|
||||||
0
|
0
|
||||||
512
|
512
|
||||||
MItem
|
MItem
|
||||||
10
|
11
|
||||||
tree_cmd.c
|
train_gui.c
|
||||||
513
|
513
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2256,8 +2256,8 @@ WVList
|
||||||
0
|
0
|
||||||
516
|
516
|
||||||
MItem
|
MItem
|
||||||
18
|
10
|
||||||
tunnelbridge_cmd.c
|
tree_cmd.c
|
||||||
517
|
517
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2274,8 +2274,8 @@ WVList
|
||||||
0
|
0
|
||||||
520
|
520
|
||||||
MItem
|
MItem
|
||||||
15
|
18
|
||||||
unmovable_cmd.c
|
tunnelbridge_cmd.c
|
||||||
521
|
521
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2292,8 +2292,8 @@ WVList
|
||||||
0
|
0
|
||||||
524
|
524
|
||||||
MItem
|
MItem
|
||||||
9
|
15
|
||||||
vehicle.c
|
unmovable_cmd.c
|
||||||
525
|
525
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2310,8 +2310,8 @@ WVList
|
||||||
0
|
0
|
||||||
528
|
528
|
||||||
MItem
|
MItem
|
||||||
13
|
9
|
||||||
vehicle_gui.c
|
vehicle.c
|
||||||
529
|
529
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2328,8 +2328,8 @@ WVList
|
||||||
0
|
0
|
||||||
532
|
532
|
||||||
MItem
|
MItem
|
||||||
19
|
13
|
||||||
video\dedicated_v.c
|
vehicle_gui.c
|
||||||
533
|
533
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2346,8 +2346,8 @@ WVList
|
||||||
0
|
0
|
||||||
536
|
536
|
||||||
MItem
|
MItem
|
||||||
14
|
19
|
||||||
video\null_v.c
|
video\dedicated_v.c
|
||||||
537
|
537
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2364,8 +2364,8 @@ WVList
|
||||||
0
|
0
|
||||||
540
|
540
|
||||||
MItem
|
MItem
|
||||||
13
|
14
|
||||||
video\sdl_v.c
|
video\null_v.c
|
||||||
541
|
541
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2382,8 +2382,8 @@ WVList
|
||||||
0
|
0
|
||||||
544
|
544
|
||||||
MItem
|
MItem
|
||||||
10
|
13
|
||||||
viewport.c
|
video\sdl_v.c
|
||||||
545
|
545
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2400,8 +2400,8 @@ WVList
|
||||||
0
|
0
|
||||||
548
|
548
|
||||||
MItem
|
MItem
|
||||||
11
|
10
|
||||||
water_cmd.c
|
viewport.c
|
||||||
549
|
549
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2418,8 +2418,8 @@ WVList
|
||||||
0
|
0
|
||||||
552
|
552
|
||||||
MItem
|
MItem
|
||||||
10
|
11
|
||||||
waypoint.c
|
water_cmd.c
|
||||||
553
|
553
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2436,8 +2436,8 @@ WVList
|
||||||
0
|
0
|
||||||
556
|
556
|
||||||
MItem
|
MItem
|
||||||
8
|
10
|
||||||
widget.c
|
waypoint.c
|
||||||
557
|
557
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2455,7 +2455,7 @@ WVList
|
||||||
560
|
560
|
||||||
MItem
|
MItem
|
||||||
8
|
8
|
||||||
window.c
|
widget.c
|
||||||
561
|
561
|
||||||
WString
|
WString
|
||||||
4
|
4
|
||||||
|
@ -2470,3 +2470,21 @@ WVList
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
0
|
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 <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <process.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <dos.h>
|
#include <dos.h>
|
||||||
|
|
||||||
#define INCL_DOS
|
|
||||||
#define INCL_WIN
|
#define INCL_WIN
|
||||||
#define INCL_WINCLIPBOARD
|
#define INCL_WINCLIPBOARD
|
||||||
|
|
||||||
|
@ -632,28 +630,6 @@ bool InsertTextBufferClipboard(Textbuf *tb)
|
||||||
return false;
|
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)
|
void CSleep(int milliseconds)
|
||||||
{
|
{
|
||||||
|
|
21
saveload.c
21
saveload.c
|
@ -21,6 +21,7 @@
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
#include "vehicle.h"
|
#include "vehicle.h"
|
||||||
#include "station.h"
|
#include "station.h"
|
||||||
|
#include "thread.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "saveload.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
|
/** We have written the whole game into memory, _save_pool, now find
|
||||||
* and appropiate compressor and start writing to file.
|
* and appropiate compressor and start writing to file.
|
||||||
*/
|
*/
|
||||||
static bool SaveFileToDisk(void *ptr)
|
static void SaveFileToDisk(void* arg)
|
||||||
{
|
{
|
||||||
const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format);
|
const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format);
|
||||||
/* XXX - backup _sl.buf cause it is used internally by the writer
|
/* 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);
|
ShowErrorMessage(STR_4007_GAME_SAVE_FAILED, STR_NULL, 0, 0);
|
||||||
|
|
||||||
SaveFileDone();
|
SaveFileDone();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have written our stuff to memory, now write it to file! */
|
/* We have written our stuff to memory, now write it to file! */
|
||||||
|
@ -1292,9 +1293,18 @@ static bool SaveFileToDisk(void *ptr)
|
||||||
fclose(_sl.fh);
|
fclose(_sl.fh);
|
||||||
|
|
||||||
SaveFileDone();
|
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
|
* Main Save or Load function where the high-level saveload functions are
|
||||||
* handled. It opens the savegame, selects format and checks versions
|
* 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 */
|
/* An instance of saving is already active, so wait until it is done */
|
||||||
if (_ts.saveinprogress) {
|
if (_ts.saveinprogress) {
|
||||||
if (!_do_autosave) ShowErrorMessage(_error_message, STR_SAVE_STILL_IN_PROGRESS, 0, 0);
|
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
|
// nonsense to do an autosave while we were still saving our game, so skip it
|
||||||
if (_do_autosave) return SL_OK;
|
if (_do_autosave) return SL_OK;
|
||||||
}
|
}
|
||||||
|
@ -1379,7 +1389,8 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode)
|
||||||
SlWriteFill(); // flush the save buffer
|
SlWriteFill(); // flush the save buffer
|
||||||
|
|
||||||
/* Write to file */
|
/* 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...");
|
DEBUG(misc, 1) ("cannot create savegame thread, reverting to single-threaded mode...");
|
||||||
SaveFileToDisk(NULL);
|
SaveFileToDisk(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ typedef enum SaveOrLoadMode {
|
||||||
} SaveOrLoadMode;
|
} SaveOrLoadMode;
|
||||||
|
|
||||||
SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
|
SaveOrLoadResult SaveOrLoad(const char *filename, int mode);
|
||||||
|
void WaitTillSaved(void);
|
||||||
|
|
||||||
|
|
||||||
typedef void ChunkSaveLoadProc(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 <sys/stat.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
|
#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
|
||||||
#define HAS_STATVFS
|
#define HAS_STATVFS
|
||||||
|
@ -515,29 +512,6 @@ bool InsertTextBufferClipboard(Textbuf *tb)
|
||||||
return false;
|
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
|
#ifdef ENABLE_NETWORK
|
||||||
|
|
||||||
|
|
19
win32.c
19
win32.c
|
@ -1193,25 +1193,6 @@ bool InsertTextBufferClipboard(Textbuf *tb)
|
||||||
return false;
|
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)
|
void CSleep(int milliseconds)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue