29 #ifndef MCR_UTIL_C11THREADS_H_ 30 #define MCR_UTIL_C11THREADS_H_ 34 #ifndef __STDC_NO_THREADS__ 39 #ifdef MCR_PLATFORM_WINDOWS 65 #define ONCE_FLAG_INIT PTHREAD_ONCE_INIT 69 #define C11THREADS_NO_TIMED_MUTEX 72 #ifdef C11THREADS_NO_TIMED_MUTEX 73 #define PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_NORMAL 74 #define C11THREADS_TIMEDLOCK_POLL_INTERVAL 5000000 78 typedef pthread_t thrd_t;
79 typedef pthread_mutex_t
mtx_t;
80 typedef pthread_cond_t cnd_t;
81 typedef pthread_key_t tss_t;
82 typedef pthread_once_t once_flag;
84 typedef int (*thrd_start_t)(
void *);
85 typedef void (*tss_dtor_t)(
void *);
103 static inline int thrd_create(thrd_t * thr, thrd_start_t func,
void *arg)
108 return pthread_create(thr, 0, (
void *(*)(
void *))func,
109 arg) == 0 ? thrd_success : thrd_error;
112 static inline void thrd_exit(
int res)
114 pthread_exit((
void *)(
long)res);
117 static inline int thrd_join(thrd_t thr,
int *res)
121 if (pthread_join(thr, &retval) != 0) {
130 static inline int thrd_detach(thrd_t thr)
132 return pthread_detach(thr) == 0 ? thrd_success : thrd_error;
135 static inline thrd_t thrd_current(
void)
137 return pthread_self();
140 static inline int thrd_equal(thrd_t a, thrd_t b)
142 return pthread_equal(a, b);
145 static inline void thrd_sleep(
const struct timespec *ts_in,
152 res = nanosleep(&ts, &rem);
154 }
while (res == -1 && errno == EINTR);
161 static inline void thrd_yield(
void)
168 static inline int mtx_init(mtx_t * mtx,
int type)
171 pthread_mutexattr_t attr;
173 pthread_mutexattr_init(&attr);
175 if (type & mtx_timed) {
176 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP);
178 if (type & mtx_recursive) {
179 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
182 res = pthread_mutex_init(mtx, &attr) == 0 ? thrd_success : thrd_error;
183 pthread_mutexattr_destroy(&attr);
187 static inline void mtx_destroy(mtx_t * mtx)
189 pthread_mutex_destroy(mtx);
192 static inline int mtx_lock(mtx_t * mtx)
194 int res = pthread_mutex_lock(mtx);
195 if (res == EDEADLK) {
198 return res == 0 ? thrd_success : thrd_error;
201 static inline int mtx_trylock(mtx_t * mtx)
203 int res = pthread_mutex_trylock(mtx);
207 return res == 0 ? thrd_success : thrd_error;
210 static inline int mtx_timedlock(mtx_t * mtx,
const struct timespec *ts)
213 #ifdef C11THREADS_NO_TIMED_MUTEX 218 sleeptime.tv_sec = 0;
219 sleeptime.tv_nsec = C11THREADS_TIMEDLOCK_POLL_INTERVAL;
221 while ((res = pthread_mutex_trylock(mtx)) == EBUSY) {
222 gettimeofday(&now, NULL);
224 if (now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec &&
225 (now.tv_usec * 1000) >= ts->tv_nsec)) {
226 return thrd_timedout;
229 nanosleep(&sleeptime, NULL);
232 if ((res = pthread_mutex_timedlock(mtx, ts)) == ETIMEDOUT) {
233 return thrd_timedout;
236 return res == 0 ? thrd_success : thrd_error;
239 static inline int mtx_unlock(mtx_t * mtx)
241 return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;
246 static inline int cnd_init(cnd_t * cond)
248 return pthread_cond_init(cond, 0) == 0 ? thrd_success : thrd_error;
251 static inline void cnd_destroy(cnd_t * cond)
253 pthread_cond_destroy(cond);
256 static inline int cnd_signal(cnd_t * cond)
258 return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
261 static inline int cnd_broadcast(cnd_t * cond)
263 return pthread_cond_broadcast(cond) == 0 ? thrd_success : thrd_error;
266 static inline int cnd_wait(cnd_t * cond, mtx_t * mtx)
268 return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
276 if ((res = pthread_cond_timedwait(cond, mtx, ts)) != 0) {
277 return res == ETIMEDOUT ? thrd_timedout : thrd_error;
284 static inline int tss_create(tss_t * key, tss_dtor_t
dtor)
286 return pthread_key_create(key, dtor) == 0 ? thrd_success : thrd_error;
289 static inline void tss_delete(tss_t key)
291 pthread_key_delete(key);
294 static inline int tss_set(tss_t key,
void *val)
296 return pthread_setspecific(key, val) == 0 ? thrd_success : thrd_error;
299 static inline void *tss_get(tss_t key)
301 return pthread_getspecific(key);
306 static inline void call_once(once_flag * flag,
void (*func)(
void))
308 pthread_once(flag, func);
MCR_API int cnd_timedwait(cnd_t *cond, mtx_t *mutex, const struct timespec *time_point)
MCR_API int cnd_wait(cnd_t *cond, mtx_t *mutex)