c11threads
diff c11threads.h @ 0:056c9db89e79
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 24 Sep 2012 12:32:42 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/c11threads.h Mon Sep 24 12:32:42 2012 +0300 1.3 @@ -0,0 +1,254 @@ 1.4 +#ifndef C11THREADS_H_ 1.5 +#define C11THREADS_H_ 1.6 + 1.7 +#include <time.h> 1.8 +#include <errno.h> 1.9 +#include <pthread.h> 1.10 +#include <sched.h> /* for sched_yield */ 1.11 +#include <sys/time.h> 1.12 + 1.13 +#define ONCE_FLAG_INIT PTHREAD_ONCE_INIT 1.14 + 1.15 +/* types */ 1.16 +typedef pthread_t thrd_t; 1.17 +typedef pthread_mutex_t mtx_t; 1.18 +typedef pthread_cond_t cnd_t; 1.19 +typedef pthread_key_t tss_t; 1.20 +typedef pthread_once_t once_flag; 1.21 + 1.22 +typedef void (*thrd_start_t)(void*); 1.23 +typedef void (*tss_dtor_t)(void*); 1.24 + 1.25 + 1.26 +typedef struct { 1.27 + time_t sec; 1.28 + long nsec; 1.29 +} xtime; 1.30 + 1.31 +enum { 1.32 + mtx_plain, 1.33 + mtx_recursive, 1.34 + mtx_timed, 1.35 + mtx_try 1.36 +}; 1.37 + 1.38 +enum { 1.39 + thrd_success, 1.40 + thrd_busy, 1.41 + thrd_error, 1.42 + thrd_nomem 1.43 +}; 1.44 + 1.45 + 1.46 +/* ---- thread management ---- */ 1.47 + 1.48 +static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) 1.49 +{ 1.50 + /* XXX there's a third possible value returned according to the standard: 1.51 + * thrd_nomem. but it doesn't seem to correspond to any pthread_create errors. 1.52 + */ 1.53 + return pthread_create(thr, 0, (void*(*)(void*))func, arg) == 0 ? thrd_success : thrd_error; 1.54 +} 1.55 + 1.56 +static inline void thrd_exit(int res) 1.57 +{ 1.58 + pthread_exit((void*)(long)res); 1.59 +} 1.60 + 1.61 +static inline int thrd_join(thrd_t thr, int *res) 1.62 +{ 1.63 + void *retval; 1.64 + 1.65 + if(pthread_join(thr, &retval) != 0) { 1.66 + return thrd_error; 1.67 + } 1.68 + if(res) { 1.69 + *res = (long)retval; 1.70 + } 1.71 + return thrd_success; 1.72 +} 1.73 + 1.74 +static inline int thrd_detatch(thrd_t thr) 1.75 +{ 1.76 + return pthread_detach(thr) == 0 ? thrd_success : thrd_error; 1.77 +} 1.78 + 1.79 +static inline thrd_t thrd_current(void) 1.80 +{ 1.81 + return pthread_self(); 1.82 +} 1.83 + 1.84 +static inline int thrd_equal(thrd_t a, thrd_t b) 1.85 +{ 1.86 + return pthread_equal(a, b); 1.87 +} 1.88 + 1.89 +static inline void thrd_sleep(const xtime *xt) 1.90 +{ 1.91 + int res; 1.92 + struct timespec ts; 1.93 + ts.tv_sec = (long)xt->sec; 1.94 + ts.tv_nsec = xt->nsec; 1.95 + 1.96 + do { 1.97 + struct timespec rem; 1.98 + res = nanosleep(&ts, &rem); 1.99 + ts = rem; 1.100 + } while(res == -1 && errno == EINTR); 1.101 +} 1.102 + 1.103 +static inline void thrd_yield(void) 1.104 +{ 1.105 + sched_yield(); 1.106 +} 1.107 + 1.108 +/* ---- mutexes ---- */ 1.109 + 1.110 +static inline int mtx_init(mtx_t *mtx, int type) 1.111 +{ 1.112 + int res; 1.113 + pthread_mutexattr_t attr; 1.114 + 1.115 + pthread_mutexattr_init(&attr); 1.116 + 1.117 + /* XXX I don't think these are exactly correct semantics */ 1.118 + if(type & mtx_try) { 1.119 + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); 1.120 + } 1.121 + if(type & mtx_timed) { 1.122 + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP); 1.123 + } 1.124 + if(type & mtx_recursive) { 1.125 + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 1.126 + } 1.127 + 1.128 + res = pthread_mutex_init(mtx, &attr) == 0 ? thrd_success : thrd_error; 1.129 + pthread_mutexattr_destroy(&attr); 1.130 + return res; 1.131 +} 1.132 + 1.133 +static inline void mtx_destroy(mtx_t *mtx) 1.134 +{ 1.135 + pthread_mutex_destroy(mtx); 1.136 +} 1.137 + 1.138 +static inline int mtx_lock(mtx_t *mtx) 1.139 +{ 1.140 + int res = pthread_mutex_lock(mtx); 1.141 + if(res == EDEADLK) { 1.142 + return thrd_busy; 1.143 + } 1.144 + return res == 0 ? thrd_success : thrd_error; 1.145 +} 1.146 + 1.147 +static inline int mtx_trylock(mtx_t *mtx) 1.148 +{ 1.149 + int res = pthread_mutex_trylock(mtx); 1.150 + if(res == EBUSY) { 1.151 + return thrd_busy; 1.152 + } 1.153 + return res == 0 ? thrd_success : thrd_error; 1.154 +} 1.155 + 1.156 +static inline int mtx_timedlock(mtx_t *mtx, const xtime *xt) 1.157 +{ 1.158 + int res; 1.159 + struct timespec ts; 1.160 + 1.161 + ts.tv_sec = (long)xt->sec; 1.162 + ts.tv_nsec = xt->nsec; 1.163 + 1.164 + if((res = pthread_mutex_timedlock(mtx, &ts)) == EBUSY) { 1.165 + return thrd_busy; 1.166 + } 1.167 + return res == 0 ? thrd_success : thrd_error; 1.168 +} 1.169 + 1.170 +static inline int mtx_unlock(mtx_t *mtx) 1.171 +{ 1.172 + return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error; 1.173 +} 1.174 + 1.175 +/* ---- condition variables ---- */ 1.176 + 1.177 +static inline int cnd_init(cnd_t *cond) 1.178 +{ 1.179 + return pthread_cond_init(cond, 0) == 0 ? thrd_success : thrd_error; 1.180 +} 1.181 + 1.182 +static inline void cnd_destroy(cnd_t *cond) 1.183 +{ 1.184 + pthread_cond_destroy(cond); 1.185 +} 1.186 + 1.187 +static inline int cnd_signal(cnd_t *cond) 1.188 +{ 1.189 + return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error; 1.190 +} 1.191 + 1.192 +static inline int cnd_broadcast(cnd_t *cond) 1.193 +{ 1.194 + return pthread_cond_broadcast(cond) == 0 ? thrd_success : thrd_error; 1.195 +} 1.196 + 1.197 +static inline int cnd_wait(cnd_t *cond, mtx_t *mtx) 1.198 +{ 1.199 + return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error; 1.200 +} 1.201 + 1.202 +static inline int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt) 1.203 +{ 1.204 + int res; 1.205 + struct timespec ts; 1.206 + 1.207 + ts.tv_sec = (long)xt->sec; 1.208 + ts.tv_nsec = xt->nsec; 1.209 + 1.210 + if((res = pthread_cond_timedwait(cond, mtx, &ts)) != 0) { 1.211 + return res == ETIMEDOUT ? thrd_busy : thrd_error; 1.212 + } 1.213 + return thrd_success; 1.214 +} 1.215 + 1.216 +/* ---- thread-specific data ---- */ 1.217 + 1.218 +static inline int tss_create(tss_t *key, tss_dtor_t dtor) 1.219 +{ 1.220 + return pthread_key_create(key, dtor) == 0 ? thrd_success : thrd_error; 1.221 +} 1.222 + 1.223 +static inline void tss_delete(tss_t key) 1.224 +{ 1.225 + pthread_key_delete(key); 1.226 +} 1.227 + 1.228 +static inline int tss_set(tss_t key, void *val) 1.229 +{ 1.230 + return pthread_setspecific(key, val) == 0 ? thrd_success : thrd_error; 1.231 +} 1.232 + 1.233 +static inline void *tss_get(tss_t key) 1.234 +{ 1.235 + return pthread_getspecific(key); 1.236 +} 1.237 + 1.238 +/* ---- misc ---- */ 1.239 + 1.240 +static inline void call_once(once_flag *flag, void (*func)(void)) 1.241 +{ 1.242 + pthread_once(flag, func); 1.243 +} 1.244 + 1.245 +/* TODO take base into account */ 1.246 +static inline int xtime_get(xtime *xt, int base) 1.247 +{ 1.248 + struct timeval tv; 1.249 + 1.250 + gettimeofday(&tv, 0); 1.251 + 1.252 + xt->sec = tv.tv_sec; 1.253 + xt->nsec = tv.tv_usec * 1000; 1.254 + return base; 1.255 +} 1.256 + 1.257 +#endif /* C11THREADS_H_ */