blob: 2d2d427b63018766971ed332dbc437dce5ca571d (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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);
}
|