aboutsummaryrefslogtreecommitdiff
path: root/src/threads.cc
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-19 03:13:48 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-19 03:13:48 -0300
commitbd3a6a04601749cbde007eaabf803fb602ee2783 (patch)
tree476b89932627aa73ad88de22d37e4617bbdb1795 /src/threads.cc
parente5b8aadd493b8b5df4ed661f2491de33d634b001 (diff)
downloadgame-bd3a6a04601749cbde007eaabf803fb602ee2783.tar.gz
game-bd3a6a04601749cbde007eaabf803fb602ee2783.zip
beginning of `communication.cc`
Diffstat (limited to 'src/threads.cc')
-rw-r--r--src/threads.cc158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/threads.cc b/src/threads.cc
new file mode 100644
index 0000000..a7acb41
--- /dev/null
+++ b/src/threads.cc
@@ -0,0 +1,158 @@
+#include "threads.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;
+}
+
+ThreadHandle StartThread(ThreadFunction *Function, void *Argument, size_t StackSize, bool Detach){
+ TThreadStarter *Starter = new TThreadStarter;
+ Starter->Function = Function;
+ Starter->Argument = Argument;
+ Starter->Detach = Detach;
+
+ pthread_t Handle;
+ pthread_attr_t Attr;
+ pthread_attr_init(&Attr);
+ pthread_attr_setstacksize(&Attr, StackSize);
+ int err = pthread_create(&Handle, &Attr, ThreadStarter, Starter);
+ pthread_attr_destroy(&Attr);
+ 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;
+}
+
+ThreadHandle StartThread(ThreadFunction *Function, void *Argument, void *Stack, size_t StackSize, bool Detach){
+ TThreadStarter *Starter = new TThreadStarter;
+ Starter->Function = Function;
+ Starter->Argument = Argument;
+ Starter->Detach = Detach;
+
+ pthread_t Handle;
+ pthread_attr_t Attr;
+ pthread_attr_init(&Attr);
+ pthread_attr_setstack(&Attr, Stack, StackSize);
+ int err = pthread_create(&Handle, &Attr, ThreadStarter, Starter);
+ pthread_attr_destroy(&Attr);
+ 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, (void**)&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);
+}