threads.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #ifndef AL_THREADS_H
  2. #define AL_THREADS_H
  3. #include <time.h>
  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif
  7. enum {
  8. althrd_success = 0,
  9. althrd_error,
  10. althrd_nomem,
  11. althrd_timedout,
  12. althrd_busy
  13. };
  14. enum {
  15. almtx_plain = 0,
  16. almtx_recursive = 1,
  17. almtx_timed = 2
  18. };
  19. typedef int (*althrd_start_t)(void*);
  20. typedef void (*altss_dtor_t)(void*);
  21. #define AL_TIME_UTC 1
  22. #ifdef _WIN32
  23. #define WIN32_LEAN_AND_MEAN
  24. #include <windows.h>
  25. #if !defined(_TIMESPEC_DEFINED) && !(defined(_MSC_VER) && (_MSC_VER >= 1900))
  26. #define _TIMESPEC_DEFINED
  27. struct timespec {
  28. time_t tv_sec;
  29. long tv_nsec;
  30. };
  31. struct itimerspec {
  32. struct timespec it_interval;
  33. struct timespec it_value;
  34. };
  35. #endif
  36. typedef DWORD althrd_t;
  37. typedef CRITICAL_SECTION almtx_t;
  38. #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
  39. typedef CONDITION_VARIABLE alcnd_t;
  40. #else
  41. typedef struct { void *Ptr; } alcnd_t;
  42. #endif
  43. typedef DWORD altss_t;
  44. typedef LONG alonce_flag;
  45. #define AL_ONCE_FLAG_INIT 0
  46. int althrd_sleep(const struct timespec *ts, struct timespec *rem);
  47. void alcall_once(alonce_flag *once, void (*callback)(void));
  48. inline althrd_t althrd_current(void)
  49. {
  50. return GetCurrentThreadId();
  51. }
  52. inline int althrd_equal(althrd_t thr0, althrd_t thr1)
  53. {
  54. return thr0 == thr1;
  55. }
  56. inline void althrd_exit(int res)
  57. {
  58. ExitThread(res);
  59. }
  60. inline void althrd_yield(void)
  61. {
  62. SwitchToThread();
  63. }
  64. inline int almtx_lock(almtx_t *mtx)
  65. {
  66. if(!mtx) return althrd_error;
  67. EnterCriticalSection(mtx);
  68. return althrd_success;
  69. }
  70. inline int almtx_unlock(almtx_t *mtx)
  71. {
  72. if(!mtx) return althrd_error;
  73. LeaveCriticalSection(mtx);
  74. return althrd_success;
  75. }
  76. inline int almtx_trylock(almtx_t *mtx)
  77. {
  78. if(!mtx) return althrd_error;
  79. if(!TryEnterCriticalSection(mtx))
  80. return althrd_busy;
  81. return althrd_success;
  82. }
  83. inline void *altss_get(altss_t tss_id)
  84. {
  85. return TlsGetValue(tss_id);
  86. }
  87. inline int altss_set(altss_t tss_id, void *val)
  88. {
  89. if(TlsSetValue(tss_id, val) == 0)
  90. return althrd_error;
  91. return althrd_success;
  92. }
  93. #else
  94. #include <stdint.h>
  95. #include <errno.h>
  96. #include <pthread.h>
  97. typedef pthread_t althrd_t;
  98. typedef pthread_mutex_t almtx_t;
  99. typedef pthread_cond_t alcnd_t;
  100. typedef pthread_key_t altss_t;
  101. typedef pthread_once_t alonce_flag;
  102. #define AL_ONCE_FLAG_INIT PTHREAD_ONCE_INIT
  103. inline althrd_t althrd_current(void)
  104. {
  105. return pthread_self();
  106. }
  107. inline int althrd_equal(althrd_t thr0, althrd_t thr1)
  108. {
  109. return pthread_equal(thr0, thr1);
  110. }
  111. inline void althrd_exit(int res)
  112. {
  113. pthread_exit((void*)(intptr_t)res);
  114. }
  115. inline void althrd_yield(void)
  116. {
  117. sched_yield();
  118. }
  119. inline int althrd_sleep(const struct timespec *ts, struct timespec *rem)
  120. {
  121. int ret = nanosleep(ts, rem);
  122. if(ret != 0)
  123. {
  124. ret = ((errno==EINTR) ? -1 : -2);
  125. errno = 0;
  126. }
  127. return ret;
  128. }
  129. inline int almtx_lock(almtx_t *mtx)
  130. {
  131. if(pthread_mutex_lock(mtx) != 0)
  132. return althrd_error;
  133. return althrd_success;
  134. }
  135. inline int almtx_unlock(almtx_t *mtx)
  136. {
  137. if(pthread_mutex_unlock(mtx) != 0)
  138. return althrd_error;
  139. return althrd_success;
  140. }
  141. inline int almtx_trylock(almtx_t *mtx)
  142. {
  143. int ret = pthread_mutex_trylock(mtx);
  144. switch(ret)
  145. {
  146. case 0: return althrd_success;
  147. case EBUSY: return althrd_busy;
  148. }
  149. return althrd_error;
  150. }
  151. inline void *altss_get(altss_t tss_id)
  152. {
  153. return pthread_getspecific(tss_id);
  154. }
  155. inline int altss_set(altss_t tss_id, void *val)
  156. {
  157. if(pthread_setspecific(tss_id, val) != 0)
  158. return althrd_error;
  159. return althrd_success;
  160. }
  161. inline void alcall_once(alonce_flag *once, void (*callback)(void))
  162. {
  163. pthread_once(once, callback);
  164. }
  165. #endif
  166. int althrd_create(althrd_t *thr, althrd_start_t func, void *arg);
  167. int althrd_detach(althrd_t thr);
  168. int althrd_join(althrd_t thr, int *res);
  169. void althrd_setname(althrd_t thr, const char *name);
  170. int almtx_init(almtx_t *mtx, int type);
  171. void almtx_destroy(almtx_t *mtx);
  172. int almtx_timedlock(almtx_t *mtx, const struct timespec *ts);
  173. int alcnd_init(alcnd_t *cond);
  174. int alcnd_signal(alcnd_t *cond);
  175. int alcnd_broadcast(alcnd_t *cond);
  176. int alcnd_wait(alcnd_t *cond, almtx_t *mtx);
  177. int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point);
  178. void alcnd_destroy(alcnd_t *cond);
  179. int altss_create(altss_t *tss_id, altss_dtor_t callback);
  180. void altss_delete(altss_t tss_id);
  181. int altimespec_get(struct timespec *ts, int base);
  182. void al_nssleep(unsigned long nsec);
  183. #ifdef __cplusplus
  184. }
  185. #endif
  186. #endif /* AL_THREADS_H */