77 #include <jasper/jas_config.h>
82 #if defined(JAS_THREADS)
87 #if defined(JAS_THREADS_C11)
89 #include <stdatomic.h>
90 #elif defined(JAS_THREADS_PTHREAD)
93 #elif defined(JAS_THREADS_WIN32)
96 #include <processthreadsapi.h>
114 #if defined(JAS_THREADS)
115 #if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY)
121 #if defined(JAS_THREADS_C11)
122 # define JAS_THREADS_IMPL "C11"
123 # define JAS_USE_SPINLOCK
124 #elif defined(JAS_THREADS_PTHREAD)
125 # define JAS_THREADS_IMPL "PTHREAD"
126 # undef JAS_USE_SPINLOCK
127 #elif defined(JAS_THREADS_WIN32)
128 # define JAS_THREADS_IMPL "WIN32"
129 # define JAS_USE_SPINLOCK
137 #if defined(JAS_THREADS_C11)
138 # define JAS_USE_SPINLOCK
142 #elif defined(JAS_THREADS_PTHREAD)
144 # undef JAS_USE_SPINLOCK
145 #elif defined(JAS_THREADS_WIN32)
146 # define JAS_USE_SPINLOCK
153 #if defined(JAS_THREADS_C11)
154 #define JAS_SPINLOCK_INITIALIZER {ATOMIC_FLAG_INIT}
155 #elif defined(JAS_THREADS_PTHREAD)
157 #elif defined(JAS_THREADS_WIN32)
158 #define JAS_SPINLOCK_INITIALIZER {0}
166 #if defined(JAS_THREADS_C11)
167 typedef mtx_t jas_basicmutex_t;
168 #elif defined(JAS_THREADS_PTHREAD)
169 typedef pthread_mutex_t jas_basicmutex_t;
170 #elif defined(JAS_THREADS_WIN32)
171 typedef CRITICAL_SECTION jas_basicmutex_t;
175 #if defined(JAS_THREADS_C11)
176 #undef JAS_BASICMUTEX_INITIALIZER
177 #elif defined(JAS_THREADS_PTHREAD)
178 #define JAS_BASICMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
179 #elif defined(JAS_THREADS_WIN32)
180 #define JAS_BASICMUTEX_INITIALIZER
187 #if defined(JAS_USE_SPINLOCK)
188 # define jas_mutex_t jas_spinlock_t
189 # define JAS_MUTEX_INITIALIZER JAS_SPINLOCK_INITIALIZER
190 # define jas_mutex_init jas_spinlock_init
191 # define jas_mutex_cleanup jas_spinlock_cleanup
192 # define jas_mutex_lock jas_spinlock_lock
193 # define jas_mutex_unlock jas_spinlock_unlock
195 # define jas_mutex_t jas_basicmutex_t
196 # define JAS_MUTEX_INITIALIZER JAS_BASICMUTEX_INITIALIZER
197 # define jas_mutex_init jas_basicmutex_init
198 # define jas_mutex_cleanup jas_basicmutex_cleanup
199 # define jas_mutex_lock jas_basicmutex_lock
200 # define jas_mutex_unlock jas_basicmutex_unlock
208 #if defined(JAS_THREADS_C11)
209 typedef once_flag jas_once_flag_t;
210 #elif defined(JAS_THREADS_PTHREAD)
211 typedef pthread_once_t jas_once_flag_t;
212 #elif defined(JAS_THREADS_WIN32)
214 volatile LONG status;
219 #if defined(JAS_THREADS_C11)
220 # define JAS_ONCE_FLAG_INIT ONCE_FLAG_INIT
221 #elif defined(JAS_THREADS_PTHREAD)
222 # define JAS_ONCE_FLAG_INIT PTHREAD_ONCE_INIT
223 #elif defined(JAS_THREADS_WIN32)
224 # define JAS_ONCE_FLAG_INIT {0}
231 #if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY)
234 #if defined(JAS_THREADS_C11)
235 typedef thrd_t jas_thread_id_t;
236 #elif defined(JAS_THREADS_PTHREAD)
237 typedef pthread_t jas_thread_id_t;
238 #elif defined(JAS_THREADS_WIN32)
239 typedef HANDLE jas_thread_id_t;
243 #if defined(JAS_THREADS_C11)
244 typedef thrd_t jas_thread_t;
245 #elif defined(JAS_THREADS_PTHREAD)
252 #elif defined(JAS_THREADS_WIN32)
260 static inline void jas_thread_yield(
void);
269 #if defined(JAS_THREADS_C11)
270 typedef tss_t jas_tss_t;
271 #elif defined(JAS_THREADS_PTHREAD)
272 typedef pthread_key_t jas_tss_t;
273 #elif defined(JAS_THREADS_WIN32)
274 typedef DWORD jas_tss_t;
282 #if defined(JAS_USE_SPINLOCK)
295 static inline int jas_spinlock_init(jas_spinlock_t *mtx)
298 #if defined(JAS_THREADS_C11)
299 atomic_flag_clear(&mtx->flag);
301 #elif defined(JAS_THREADS_PTHREAD)
305 #elif defined(JAS_THREADS_WIN32)
306 InterlockedExchange(&mtx->flag, 0);
322 static inline int jas_spinlock_cleanup(jas_spinlock_t *mtx)
325 #if defined(JAS_THREADS_C11)
328 #elif defined(JAS_THREADS_PTHREAD)
332 #elif defined(JAS_THREADS_WIN32)
349 static inline int jas_spinlock_lock(jas_spinlock_t *mtx)
352 #if defined(JAS_THREADS_C11)
353 while (atomic_flag_test_and_set(&mtx->flag)) {}
355 #elif defined(JAS_THREADS_PTHREAD)
359 #elif defined(JAS_THREADS_WIN32)
360 while (InterlockedCompareExchange(&mtx->flag, 1, 0)) {}
376 static inline int jas_spinlock_unlock(jas_spinlock_t *mtx)
379 #if defined(JAS_THREADS_C11)
380 atomic_flag_clear(&mtx->flag);
382 #elif defined(JAS_THREADS_PTHREAD)
386 #elif defined(JAS_THREADS_WIN32)
387 InterlockedExchange(&mtx->flag, 0);
399 static inline int jas_basicmutex_init(jas_basicmutex_t *mtx)
402 #if defined(JAS_THREADS_C11)
403 return mtx_init(mtx, mtx_plain) == thrd_success ? 0 : -1;
404 #elif defined(JAS_THREADS_PTHREAD)
405 return pthread_mutex_init(mtx, 0);
406 #elif defined(JAS_THREADS_WIN32)
407 InitializeCriticalSection(mtx);
413 static inline int jas_basicmutex_cleanup(jas_basicmutex_t *mtx)
416 #if defined(JAS_THREADS_C11)
419 #elif defined(JAS_THREADS_PTHREAD)
420 return pthread_mutex_destroy(mtx);
421 #elif defined(JAS_THREADS_WIN32)
422 DeleteCriticalSection(mtx);
428 static inline int jas_basicmutex_lock(jas_basicmutex_t *mtx)
431 #if defined(JAS_THREADS_C11)
432 return mtx_lock(mtx);
433 #elif defined(JAS_THREADS_PTHREAD)
434 return pthread_mutex_lock(mtx);
435 #elif defined(JAS_THREADS_WIN32)
436 EnterCriticalSection(mtx);
442 static inline int jas_basicmutex_unlock(jas_basicmutex_t *mtx)
445 #if defined(JAS_THREADS_C11)
446 return mtx_unlock(mtx);
447 #elif defined(JAS_THREADS_PTHREAD)
448 return pthread_mutex_unlock(mtx);
449 #elif defined(JAS_THREADS_WIN32)
450 LeaveCriticalSection(mtx);
473 int jas_tss_create(jas_tss_t *tss,
void (*destructor)(
void *))
476 #if defined(JAS_THREADS_C11)
477 return tss_create(tss, destructor) == thrd_success ? 0 : -1;
478 #elif defined(JAS_THREADS_PTHREAD)
479 return pthread_key_create(tss, destructor);
480 #elif defined(JAS_THREADS_WIN32)
485 if ((
id = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
504 void jas_tss_delete(jas_tss_t tss)
506 #if defined(JAS_THREADS_C11)
508 #elif defined(JAS_THREADS_PTHREAD)
509 pthread_key_delete(tss);
510 #elif defined(JAS_THREADS_WIN32)
525 void *jas_tss_get(jas_tss_t tss)
527 #if defined(JAS_THREADS_C11)
529 #elif defined(JAS_THREADS_PTHREAD)
530 return pthread_getspecific(tss);
531 #elif defined(JAS_THREADS_WIN32)
532 return TlsGetValue(tss);
547 int jas_tss_set(jas_tss_t tss,
void *value)
549 #if defined(JAS_THREADS_C11)
550 return tss_set(tss, value) == thrd_success ? 0 : -1;
551 #elif defined(JAS_THREADS_PTHREAD)
552 return pthread_setspecific(tss, value);
553 #elif defined(JAS_THREADS_WIN32)
554 return TlsSetValue(tss, value) ? 0 : -1;
572 static inline int jas_call_once(jas_once_flag_t *flag,
void (*func)(
void))
576 #if defined(JAS_THREADS_C11)
577 call_once(flag, func);
579 #elif defined(JAS_THREADS_PTHREAD)
580 return pthread_once(flag, func);
581 #elif defined(JAS_THREADS_WIN32)
582 if (InterlockedCompareExchange(&flag->status, 1, 0) == 0) {
584 InterlockedExchange(&flag->status, 2);
586 while (flag->status == 1) {
600 #if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY)
602 #if defined(JAS_THREADS_PTHREAD)
603 static void *thread_func_wrapper(
void *thread_ptr)
605 jas_thread_t *thread = JAS_CAST(jas_thread_t *, thread_ptr);
606 int result = (thread->func)(thread->arg);
607 thread->result = result;
610 #elif defined(JAS_THREADS_WIN32)
611 static unsigned __stdcall thread_func_wrapper(
void *thread_ptr)
613 jas_thread_t *thread = JAS_CAST(jas_thread_t *, thread_ptr);
614 int result = (thread->func)(thread->arg);
615 return JAS_CAST(
unsigned, result);
628 int jas_thread_compare(jas_thread_id_t x, jas_thread_id_t y)
630 #if defined(JAS_THREADS_C11)
631 return thrd_equal(x, y);
632 #elif defined(JAS_THREADS_PTHREAD)
633 return pthread_equal(x, y);
634 #elif defined(JAS_THREADS_WIN32)
635 return GetThreadId(x) == GetThreadId(y);
648 int jas_thread_create(jas_thread_t *thread,
int (*func)(
void *),
void *arg)
652 #if defined(JAS_THREADS_C11)
653 return thrd_create(thread, func, arg) == thrd_success ? 0 : -1;
654 #elif defined(JAS_THREADS_PTHREAD)
658 return pthread_create(&thread->id, 0, thread_func_wrapper, thread);
659 #elif defined(JAS_THREADS_WIN32)
663 if (!(handle = _beginthreadex(0, 0, thread_func_wrapper, thread, 0, 0))) {
666 thread->id = JAS_CAST(jas_thread_id_t, handle);
680 int jas_thread_join(jas_thread_t *thread,
int *result)
683 #if defined(JAS_THREADS_C11)
684 return thrd_join(*thread, result) == thrd_success ? 0 : -1;
685 #elif defined(JAS_THREADS_PTHREAD)
687 int ret = pthread_join(thread->id, &result_buf);
689 jas_thread_t *other_thread = JAS_CAST(jas_thread_t *, result_buf);
692 assert(other_thread);
693 *result = other_thread ? other_thread->result : 0;
697 #elif defined(JAS_THREADS_WIN32)
700 if ((w = WaitForSingleObject(thread->id, INFINITE)) != WAIT_OBJECT_0) {
704 if (!GetExitCodeThread(thread->id, &code)) {
705 CloseHandle(thread->id);
708 *result = JAS_CAST(
int, code);
710 CloseHandle(thread->id);
725 static inline void jas_thread_yield(
void)
727 #if defined(JAS_THREADS_C11)
729 #elif defined(JAS_THREADS_PTHREAD)
731 #elif defined(JAS_THREADS_WIN32)
739 void jas_thread_exit(
int result)
741 #if defined(JAS_THREADS_C11)
743 #elif defined(JAS_THREADS_PTHREAD)
746 jas_thread_t *thread = jas_thread_find(pthread_self());
747 thread->result = result;
748 pthread_exit(JAS_CAST(
void *, thread));
758 jas_thread_id_t jas_thread_current(
void)
760 #if defined(JAS_THREADS_C11)
761 return thrd_current();
762 #elif defined(JAS_THREADS_PTHREAD)
763 return pthread_self();
764 #elif defined(JAS_THREADS_WIN32)