77#include <jasper/jas_config.h>
82#if defined(JAS_THREADS)
87#if defined(JAS_THREADS_C11)
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)
167typedef mtx_t jas_basicmutex_t;
168#elif defined(JAS_THREADS_PTHREAD)
169typedef pthread_mutex_t jas_basicmutex_t;
170#elif defined(JAS_THREADS_WIN32)
171typedef 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)
209typedef once_flag jas_once_flag_t;
210#elif defined(JAS_THREADS_PTHREAD)
211typedef 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)
235typedef thrd_t jas_thread_id_t;
236#elif defined(JAS_THREADS_PTHREAD)
237typedef pthread_t jas_thread_id_t;
238#elif defined(JAS_THREADS_WIN32)
239typedef HANDLE jas_thread_id_t;
243#if defined(JAS_THREADS_C11)
244typedef thrd_t jas_thread_t;
245#elif defined(JAS_THREADS_PTHREAD)
252#elif defined(JAS_THREADS_WIN32)
260static inline void jas_thread_yield(
void);
269#if defined(JAS_THREADS_C11)
270typedef tss_t jas_tss_t;
271#elif defined(JAS_THREADS_PTHREAD)
272typedef pthread_key_t jas_tss_t;
273#elif defined(JAS_THREADS_WIN32)
274typedef DWORD jas_tss_t;
282#if defined(JAS_USE_SPINLOCK)
295static 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);
322static 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)
349static 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)) {}
376static 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);
399static 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);
413static 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);
428static 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);
442static 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);
473int 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) {
504void 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)
525void *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);
547int 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;
572static 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)
603static 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)
611static 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);
628int 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);
648int 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);
680int 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);
725static inline void jas_thread_yield(
void)
727#if defined(JAS_THREADS_C11)
729#elif defined(JAS_THREADS_PTHREAD)
731#elif defined(JAS_THREADS_WIN32)
739void 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));
758jas_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)
#define JAS_UNUSED(x)
Indicate that a variable may be unused (in order to avoid a compiler warning).
Definition jas_compiler.h:145