implement threading API

This commit is contained in:
fusion32 2025-05-22 14:43:54 -03:00
parent 297e8450d8
commit 3edeaf1f52
4 changed files with 144 additions and 14 deletions

View File

@ -1,5 +1,5 @@
## TODO NEXT
- THREADS
- Split main.hh -> common.hh, shm.hh, time.hh, util.hh
- TReadStream/TWriteStream
- TReadBuffer/TWriteBuffer
- TReadBinaryFile/TWriteBinaryFile

View File

@ -96,12 +96,6 @@ struct TDatabasePoolConnection {
bool TransactionRunning;
};
struct Semaphore {
int value;
struct pthread_mutex_t mutex;
struct pthread_cond_t condition;
};
struct TDatabaseConnectionPool {
int NumberOfConnections;
struct TDatabaseSettings DatabaseSettings;
@ -786,13 +780,6 @@ struct TFindCreatures {
bool finished;
};
typedef int (ThreadFunction)(void *);
struct TThreadStarter {
ThreadFunction *Function;
void *Argument;
bool Detach;
};
struct TReaderThreadOrder {
enum TReaderThreadOrderType OrderType;
int SectorX;

110
src/thread.cc Normal file
View File

@ -0,0 +1,110 @@
#include "thread.hh"
struct TThreadStarter {
ThreadFunction *Function;
void *Argument;
bool Detach;
};
static void *ThreadStarter(void *Pointer){
TThreadStarter *Starter = (TThreadStarter*)Pointer;
ThreadFunction *Function = Starter->Function;
void *Argument = Starter->Argument;
bool Detach = Starter->Detach;
delete Starter;
int Result = Function(Argument);
// TODO(fusion): Just store the integer as a pointer and avoid allocation?
int *ResultPointer = NULL;
if(!Detach){
ResultPointer = new int;
*ResultPointer = Result;
}
pthread_exit(ResultPointer);
return NULL; // Unreachable.
}
ThreadHandle StartThread(ThreadFunction *Function, void *Argument, bool Detach){
TThreadStarter *Starter = new TThreadStarter;
Starter->Function = Function;
Starter->Argument = Argument;
Starter->Detach = Detach;
pthread_t Handle;
int err = pthread_create(&Handle, NULL, ThreadStarter, Starter);
if(err != 0){
error("StartThread: Kann Thread nicht anlegen; Fehlercode %d.\n", err);
return INVALID_THREAD_HANDLE;
}
if(Detach){
pthread_detach(Handle);
}
return (ThreadHandle)Handle;
}
int JoinThread(ThreadHandle Handle){
int Result = 0;
int *ResultPointer;
pthread_join((pthread_t)Handle, &ResultPointer);
if(ResultPointer != NULL){
Result = *ResultPointer;
delete ResultPointer;
}
return Result;
}
void DelayThread(int Seconds, int MicroSeconds){
if(Seconds == 0 && MicroSeconds == 0){
sched_yield();
}else if(MicroSeconds == 0){
sleep(Seconds);
}else{
usleep(MicroSeconds + Seconds * 1000000);
}
}
Semaphore::Semaphore(int Value){
this->value = Value;
// TODO(fusion): These should probably be non-recoverable errors.
if(pthread_mutex_init(&this->mutex, NULL) != 0){
error("Semaphore::Semaphore: Kann Mutex nicht einrichten.\n");
}
if(pthread_cond_init(&this->condition, NULL) != 0){
error("Semaphore::Semaphore: Kann Wartebedingung nicht einrichten.\n");
}
}
Semaphore::~Semaphore(void){
if(pthread_mutex_destroy(&this->mutex) != 0){
error("Semaphore::~Semaphore: Kann Mutex nicht freigeben.\n");
}
if(pthread_cond_destroy(&this->condition) != 0){
error("Semaphore::~Semaphore: Kann Wartebedingung nicht freigeben.\n");
}
}
void Semaphore::down(void){
pthread_mutex_lock(&this->mutex);
while(this->value <= 0){ // TODO(fusion): Make sure this is always a load operation?
pthread_cond_wait(&this->condition, &this->mutex);
}
this->value -= 1;
pthread_mutex_unlock(&this->mutex);
}
void Semaphore::up(void){
pthread_mutex_lock(&this->mutex);
this->value += 1;
pthread_mutex_unlock(&this->mutex);
pthread_cond_signal(&this->condition);
}

33
src/thread.hh Normal file
View File

@ -0,0 +1,33 @@
#ifndef TIBIA_THREAD_HH_
#define TIBIA_THREAD_HH_ 1
#include "main.hh"
#include <pthread.h>
typedef pthread_t ThreadHandle;
typedef int (ThreadFunction)(void *);
// TODO(fusion): Probably have another way to tell whether the thread was
// successfully spawned or not?
constexpr ThreadHandle INVALID_THREAD_HANDLE = 0;
ThreadHandle StartThread(ThreadFunction *Function, void *Argument, bool Detach);
int JoinThread(ThreadHandle Handle);
void DelayThread(int Seconds, int MicroSeconds);
struct Semaphore {
// REGULAR FUNCTIONS
// =========================================================================
Semaphore(void);
~Semaphore(void);
void up(void);
void down(void);
// DATA
// =========================================================================
int value;
pthread_mutex_t mutex;
pthread_cond_t condition;
};
#endif //TIBIA_THREAD_HH_