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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
#ifndef AL_THREADS_H
#define AL_THREADS_H
#include <time.h>
enum {
althrd_success = 0,
althrd_nomem,
althrd_timedout,
althrd_busy,
althrd_error
};
enum {
almtx_plain = 0,
almtx_recursive = 1,
almtx_timed = 2
};
typedef int (*althrd_start_t)(void*);
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef HANDLE althrd_t;
typedef CRITICAL_SECTION almtx_t;
#ifndef __MINGW32__
struct timespec {
time_t tv_sec;
long tv_nsec;
};
#endif
int althrd_sleep(const struct timespec *ts, struct timespec *rem);
#if 0
inline althrd_t althrd_current(void)
{
/* This is wrong. GetCurrentThread() returns a psuedo-handle of -1 which
* various functions will interpret as the calling thread. There is no
* apparent way to retrieve the same handle that was returned by
* CreateThread. */
return GetCurrentThread();
}
#endif
inline int althrd_equal(althrd_t thr0, althrd_t thr1)
{
return GetThreadId(thr0) == GetThreadId(thr1);
}
inline void althrd_exit(int res)
{
ExitThread(res);
}
inline void althrd_yield(void)
{
SwitchToThread();
}
inline int almtx_lock(almtx_t *mtx)
{
if(!mtx) return althrd_error;
EnterCriticalSection(mtx);
return althrd_success;
}
inline int almtx_unlock(almtx_t *mtx)
{
if(!mtx) return althrd_error;
LeaveCriticalSection(mtx);
return althrd_success;
}
inline int almtx_trylock(almtx_t *mtx)
{
if(!mtx) return althrd_error;
if(!TryEnterCriticalSection(mtx))
return althrd_busy;
return althrd_success;
}
#else
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
typedef pthread_t althrd_t;
typedef pthread_mutex_t almtx_t;
inline althrd_t althrd_current(void)
{
return pthread_self();
}
inline int althrd_equal(althrd_t thr0, althrd_t thr1)
{
return pthread_equal(thr0, thr1);
}
inline void althrd_exit(int res)
{
pthread_exit((void*)(intptr_t)res);
}
inline void althrd_yield(void)
{
sched_yield();
}
inline int althrd_sleep(const struct timespec *ts, struct timespec *rem)
{
int ret = nanosleep(ts, rem);
if(ret != 0)
{
ret = ((errno==EINTR) ? -1 : -2);
errno = 0;
}
return ret;
}
inline int almtx_lock(almtx_t *mtx)
{
int ret = EINVAL;
if(mtx != NULL)
ret = pthread_mutex_lock(mtx);
switch(ret)
{
case 0: return althrd_success;
case EAGAIN: return althrd_busy;
}
return althrd_error;
}
inline int almtx_unlock(almtx_t *mtx)
{
if(!mtx) return althrd_error;
pthread_mutex_unlock(mtx);
return althrd_success;
}
inline int almtx_trylock(almtx_t *mtx)
{
int ret = EINVAL;
if(mtx != NULL)
ret = pthread_mutex_trylock(mtx);
switch(ret)
{
case 0: return althrd_success;
case EAGAIN:
case EBUSY: return althrd_busy;
}
return althrd_error;
}
#endif
int althrd_create(althrd_t *thr, althrd_start_t func, void *arg);
int althrd_detach(althrd_t thr);
int althrd_join(althrd_t thr, int *res);
int almtx_init(almtx_t *mtx, int type);
void almtx_destroy(almtx_t *mtx);
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts);
void SetThreadName(const char *name);
inline void al_nssleep(time_t sec, long nsec)
{
struct timespec ts, rem;
ts.tv_sec = sec;
ts.tv_nsec = nsec;
while(althrd_sleep(&ts, &rem) == -1)
ts = rem;
}
#endif /* AL_THREADS_H */
|