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
111
112
113
114
115
116
117
118
119
120
121
122
|
#include "Thread.h"
/*
Utility functions associated with threads.
*/
void
s_usleep (slong us) {
#if __WIN32__ || __WIN64__
/* We are a windows system, so we have to implement our own little sleeper.*/
Sleep (us / 1000)
#else
/* We are not a windows system, so lets assume that we have posix's nanosleep
* Taken from:
*/
struct timespec req = {0};
req.tv_sec = (int)(us / 1000);
req.tv_nsec = us * 1000000L;
nanosleep(&req, (struct timespec *)NULL);
#endif
}
char *
s_thread_status_get_name (SThreadStatus status) {
return SThreadStatusName[status];
}
/* ****************************************************************************
********************************** SMutex ************************************
**************************************************************************** */
struct SMutex {
mtx_t * mutex;
_Atomic(sboolean) locked;
};
SMutex *
s_mutex_new () {
SMutex * self = malloc (sizeof (SMutex));
self->mutex = malloc (sizeof (mtx_t));
atomic_init(&(self->locked), FALSE);
sint status = mtx_init (self->mutex, mtx_plain);
if (status == thrd_success) {
return self;
}
free (self);
s_err_print ("Could not create thrad. Error: %s.\n",
s_thread_status_get_name (status));
print_backtrace ();
return NULL;
}
void
s_mutex_free (SMutex * self) {
mtx_destroy (self->mutex);
free (self->mutex);
free (self);
}
SThreadStatus
s_mutex_lock (SMutex * self) {
sint ret_val = mtx_lock (self->mutex);
atomic_store(&(self->locked), TRUE);
return ret_val;
}
SThreadStatus
s_mutex_unlock (SMutex * self) {
sint ret_val = mtx_unlock (self->mutex);
atomic_store(&(self->locked), FALSE);
return ret_val;
}
SThreadStatus
s_mutex_check_lock (SMutex * self) {
return atomic_load(&(self->locked));
}
/* ****************************************************************************
********************************** SThread ***********************************
**************************************************************************** */
/*
* Since SThread are, effectivaly, the same as thrd_t, we can cast it
* back and forth without any real problems...?
*/
struct SThread {
thrd_t thread;
RunFunc func;
_Atomic(sboolean) is_running;
};
SThread *
s_thread_new (RunFunc func) {
SThread * self = malloc (sizeof (SThread));
self->func = func;
atomic_store (&(self->is_running), FALSE);
return self;
}
void
s_thread_free (SThread * self) {
assert (!(atomic_load(&(self->is_running))));
free (self);
}
sboolean
s_thread_run (SThread * self, spointer user_data) {
return thrd_create ((thrd_t *)self, (thrd_start_t)self->func, user_data);
atomic_store(&(self->is_running), TRUE);
}
|