/* * Copyright (c) 1999-2000 Image Power, Inc. and the University of * British Columbia. * Copyright (c) 2001-2003 Michael David Adams. * All rights reserved. */ /* __START_OF_JASPER_LICENSE__ * * JasPer License Version 2.0 * * Copyright (c) 2001-2006 Michael David Adams * Copyright (c) 1999-2000 Image Power, Inc. * Copyright (c) 1999-2000 The University of British Columbia * * All rights reserved. * * Permission is hereby granted, free of charge, to any person (the * "User") obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * 1. The above copyright notices and this permission notice (which * includes the disclaimer below) shall be included in all copies or * substantial portions of the Software. * * 2. The name of a copyright holder shall not be used to endorse or * promote products derived from the Software without specific prior * written permission. * * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. * * __END_OF_JASPER_LICENSE__ */ /*! * @file jas_thread.h * @brief Threads */ #ifndef JAS_THREAD_H#define JAS_THREAD_H /******************************************************************************\* Includes\******************************************************************************/ /* The configuration header file should be included first. */#include <jasper/jas_config.h> #include "jasper/jas_compiler.h"#include "jasper/jas_types.h" #if defined(JAS_THREADS) #include <stdlib.h>#include <assert.h> #if defined(JAS_THREADS_C11)#include <threads.h>#include <stdatomic.h>#elif defined(JAS_THREADS_PTHREAD)#include <pthread.h>#include <sched.h>#elif defined(JAS_THREADS_WIN32)#include <process.h>#include <windows.h>#include <processthreadsapi.h>#endif #endif /******************************************************************************\\******************************************************************************/ #ifdef __cplusplusextern "C" {#endif /*! * @cond DOXYGEN_EXCLUDE * @addtogroup module_threads * @{ */ #if defined(JAS_THREADS)#if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) /******************************************************************************\* Types\******************************************************************************/ #if defined(JAS_THREADS_C11)# define JAS_THREADS_IMPL "C11"# define JAS_USE_SPINLOCK#elif defined(JAS_THREADS_PTHREAD)# define JAS_THREADS_IMPL "PTHREAD"# undef JAS_USE_SPINLOCK#elif defined(JAS_THREADS_WIN32)# define JAS_THREADS_IMPL "WIN32"# define JAS_USE_SPINLOCK#endif /**************************************\* Spinlock\**************************************/ /*! Spinlock type. */#if defined(JAS_THREADS_C11)# define JAS_USE_SPINLOCKtypedef struct { atomic_flag flag;} jas_spinlock_t;#elif defined(JAS_THREADS_PTHREAD)/* There is no pthread_spinlock_t type on MacOS. */# undef JAS_USE_SPINLOCK#elif defined(JAS_THREADS_WIN32)# define JAS_USE_SPINLOCKtypedef struct { LONG flag;} jas_spinlock_t;#endif /*! Spinlock initializer. */#if defined(JAS_THREADS_C11)#define JAS_SPINLOCK_INITIALIZER {ATOMIC_FLAG_INIT}#elif defined(JAS_THREADS_PTHREAD)/* There is no pthread_spinlock_t type on MacOS. */#elif defined(JAS_THREADS_WIN32)#define JAS_SPINLOCK_INITIALIZER {0}#endif /**************************************\* Basic Mutex\**************************************/ /*! Mutex type. */#if defined(JAS_THREADS_C11)typedef mtx_t jas_basicmutex_t;#elif defined(JAS_THREADS_PTHREAD)typedef pthread_mutex_t jas_basicmutex_t;#elif defined(JAS_THREADS_WIN32)typedef CRITICAL_SECTION jas_basicmutex_t;#endif /*! Mutex initializer. */#if defined(JAS_THREADS_C11)#undef JAS_BASICMUTEX_INITIALIZER#elif defined(JAS_THREADS_PTHREAD)#define JAS_BASICMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER#elif defined(JAS_THREADS_WIN32)#define JAS_BASICMUTEX_INITIALIZER#endif /**************************************\* Mutex (Allowing Static Initialization)\**************************************/ #if defined(JAS_USE_SPINLOCK)# define jas_mutex_t jas_spinlock_t# define JAS_MUTEX_INITIALIZER JAS_SPINLOCK_INITIALIZER# define jas_mutex_init jas_spinlock_init# define jas_mutex_cleanup jas_spinlock_cleanup# define jas_mutex_lock jas_spinlock_lock# define jas_mutex_unlock jas_spinlock_unlock#else# define jas_mutex_t jas_basicmutex_t# define JAS_MUTEX_INITIALIZER JAS_BASICMUTEX_INITIALIZER# define jas_mutex_init jas_basicmutex_init# define jas_mutex_cleanup jas_basicmutex_cleanup# define jas_mutex_lock jas_basicmutex_lock# define jas_mutex_unlock jas_basicmutex_unlock#endif /**************************************\* Once Flag\**************************************/ /*! Once-flag type. */#if defined(JAS_THREADS_C11)typedef once_flag jas_once_flag_t;#elif defined(JAS_THREADS_PTHREAD)typedef pthread_once_t jas_once_flag_t;#elif defined(JAS_THREADS_WIN32)typedef struct { volatile LONG status;} jas_once_flag_t;#endif /*! Once-flag initializer. */#if defined(JAS_THREADS_C11)# define JAS_ONCE_FLAG_INIT ONCE_FLAG_INIT#elif defined(JAS_THREADS_PTHREAD)# define JAS_ONCE_FLAG_INIT PTHREAD_ONCE_INIT#elif defined(JAS_THREADS_WIN32)# define JAS_ONCE_FLAG_INIT {0}#endif /**************************************\* Threads\**************************************/ #if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) /*! Thread ID type. */#if defined(JAS_THREADS_C11)typedef thrd_t jas_thread_id_t;#elif defined(JAS_THREADS_PTHREAD)typedef pthread_t jas_thread_id_t;#elif defined(JAS_THREADS_WIN32)typedef HANDLE jas_thread_id_t;#endif /*! Thread type. */#if defined(JAS_THREADS_C11)typedef thrd_t jas_thread_t;#elif defined(JAS_THREADS_PTHREAD)typedef struct { pthread_t id; int (*func)(void *); void *arg; int result;} jas_thread_t;#elif defined(JAS_THREADS_WIN32)typedef struct { jas_thread_id_t id; int (*func)(void *); void *arg;} jas_thread_t;#endif static inline void jas_thread_yield(void); #endif /**************************************\* Thread-Specific Storage (TSS)\**************************************/ /*! Thread-specific storage type. */#if defined(JAS_THREADS_C11)typedef tss_t jas_tss_t;#elif defined(JAS_THREADS_PTHREAD)typedef pthread_key_t jas_tss_t;#elif defined(JAS_THREADS_WIN32)typedef DWORD jas_tss_t;#endif /******************************************************************************\* Spinlock\******************************************************************************/ #if defined(JAS_USE_SPINLOCK) /*!@briefInitialize a spinlock. @param mtxA pointer to the spinlock to be initialized. @returnsIf the spinlock is successfully initialized, zero is returned.Otherwise, a nonzero value is returned.*/static inline int jas_spinlock_init(jas_spinlock_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) atomic_flag_clear(&mtx->flag); return 0;#elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1;#elif defined(JAS_THREADS_WIN32) InterlockedExchange(&mtx->flag, 0); return 0;#endif} /*!@briefClean up a spinlock mutex. @param mtxA pointer to the spinlock to be cleaned up. @returnsIf the spinlock is successfully cleaned up, zero is returned.Otherwise, a nonzero value is returned.*/static inline int jas_spinlock_cleanup(jas_spinlock_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) JAS_UNUSED(mtx); return 0;#elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1;#elif defined(JAS_THREADS_WIN32) JAS_UNUSED(mtx); return 0;#endif} /*!@briefAcquire a spinlock. @param mtxA pointer to the spinlock to be acquired. @returnsIf successful, zero is returned.Otherwise, a nonzero value is returned.*/static inline int jas_spinlock_lock(jas_spinlock_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) while (atomic_flag_test_and_set(&mtx->flag)) {} return 0;#elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1;#elif defined(JAS_THREADS_WIN32) while (InterlockedCompareExchange(&mtx->flag, 1, 0)) {} return 0;#endif} /*!@briefRelease a spinlock. @param mtxA pointer to the spinlock to be released. @returnsIf the operation is successful, zero is returned.Otherwise, a nonzero value is returned.*/static inline int jas_spinlock_unlock(jas_spinlock_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) atomic_flag_clear(&mtx->flag); return 0;#elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1;#elif defined(JAS_THREADS_WIN32) InterlockedExchange(&mtx->flag, 0); return 0;#endif} #endif /******************************************************************************\* Basic Mutex\******************************************************************************/ /* For internal use only. */static inline int jas_basicmutex_init(jas_basicmutex_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) return mtx_init(mtx, mtx_plain) == thrd_success ? 0 : -1;#elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_init(mtx, 0);#elif defined(JAS_THREADS_WIN32) InitializeCriticalSection(mtx); return 0;#endif} /* For internal use only. */static inline int jas_basicmutex_cleanup(jas_basicmutex_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) mtx_destroy(mtx); return 0;#elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_destroy(mtx);#elif defined(JAS_THREADS_WIN32) DeleteCriticalSection(mtx); return 0;#endif} /* For internal use only. */static inline int jas_basicmutex_lock(jas_basicmutex_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) return mtx_lock(mtx);#elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_lock(mtx);#elif defined(JAS_THREADS_WIN32) EnterCriticalSection(mtx); return 0;#endif} /* For internal use only. */static inline int jas_basicmutex_unlock(jas_basicmutex_t *mtx){ assert(mtx);#if defined(JAS_THREADS_C11) return mtx_unlock(mtx);#elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_unlock(mtx);#elif defined(JAS_THREADS_WIN32) LeaveCriticalSection(mtx); return 0;#endif} /******************************************************************************\* Thread-Specific Storage (TSS)\******************************************************************************/ /*!@briefCreate thread-specific storage. @param tssA pointer to the TSS object to be initialized.@param destructorA function to be called when the TSS is deallocated when the thread exits. @returnsIf the operation is successful, zero is returned.Otherwise, a nonzero value is returned.*/static inlineint jas_tss_create(jas_tss_t *tss, void (*destructor)(void *)){ assert(tss);#if defined(JAS_THREADS_C11) return tss_create(tss, destructor) == thrd_success ? 0 : -1;#elif defined(JAS_THREADS_PTHREAD) return pthread_key_create(tss, destructor);#elif defined(JAS_THREADS_WIN32) if (destructor) { return -1; } DWORD id; if ((id = TlsAlloc()) == TLS_OUT_OF_INDEXES) { return -2; } *tss = id; return 0;#endif} /*!@brief Delete thread-specific storage. @param tssThe TSS to be destroyed. @returnsIf the operation is successful, zero is returned.Lines 1–500 of 795. Load more
/* * Copyright (c) 1999-2000 Image Power, Inc. and the University of * British Columbia. * Copyright (c) 2001-2003 Michael David Adams. * All rights reserved. */ /* __START_OF_JASPER_LICENSE__ * * JasPer License Version 2.0 * * Copyright (c) 2001-2006 Michael David Adams * Copyright (c) 1999-2000 Image Power, Inc. * Copyright (c) 1999-2000 The University of British Columbia * * All rights reserved. * * Permission is hereby granted, free of charge, to any person (the * "User") obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * 1. The above copyright notices and this permission notice (which * includes the disclaimer below) shall be included in all copies or * substantial portions of the Software. * * 2. The name of a copyright holder shall not be used to endorse or * promote products derived from the Software without specific prior * written permission. * * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. * * __END_OF_JASPER_LICENSE__ */ /*! * @file jas_thread.h * @brief Threads */ #ifndef JAS_THREAD_H #define JAS_THREAD_H /******************************************************************************\ * Includes \******************************************************************************/ /* The configuration header file should be included first. */ #include <jasper/jas_config.h> #include "jasper/jas_compiler.h" #include "jasper/jas_types.h" #if defined(JAS_THREADS) #include <stdlib.h> #include <assert.h> #if defined(JAS_THREADS_C11) #include <threads.h> #include <stdatomic.h> #elif defined(JAS_THREADS_PTHREAD) #include <pthread.h> #include <sched.h> #elif defined(JAS_THREADS_WIN32) #include <process.h> #include <windows.h> #include <processthreadsapi.h> #endif #endif /******************************************************************************\ \******************************************************************************/ #ifdef __cplusplus extern "C" { #endif /*! * @cond DOXYGEN_EXCLUDE * @addtogroup module_threads * @{ */ #if defined(JAS_THREADS) #if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) /******************************************************************************\ * Types \******************************************************************************/ #if defined(JAS_THREADS_C11) # define JAS_THREADS_IMPL "C11" # define JAS_USE_SPINLOCK #elif defined(JAS_THREADS_PTHREAD) # define JAS_THREADS_IMPL "PTHREAD" # undef JAS_USE_SPINLOCK #elif defined(JAS_THREADS_WIN32) # define JAS_THREADS_IMPL "WIN32" # define JAS_USE_SPINLOCK #endif /**************************************\ * Spinlock \**************************************/ /*! Spinlock type. */ #if defined(JAS_THREADS_C11) # define JAS_USE_SPINLOCK typedef struct { atomic_flag flag; } jas_spinlock_t; #elif defined(JAS_THREADS_PTHREAD) /* There is no pthread_spinlock_t type on MacOS. */ # undef JAS_USE_SPINLOCK #elif defined(JAS_THREADS_WIN32) # define JAS_USE_SPINLOCK typedef struct { LONG flag; } jas_spinlock_t; #endif /*! Spinlock initializer. */ #if defined(JAS_THREADS_C11) #define JAS_SPINLOCK_INITIALIZER {ATOMIC_FLAG_INIT} #elif defined(JAS_THREADS_PTHREAD) /* There is no pthread_spinlock_t type on MacOS. */ #elif defined(JAS_THREADS_WIN32) #define JAS_SPINLOCK_INITIALIZER {0} #endif /**************************************\ * Basic Mutex \**************************************/ /*! Mutex type. */ #if defined(JAS_THREADS_C11) typedef mtx_t jas_basicmutex_t; #elif defined(JAS_THREADS_PTHREAD) typedef pthread_mutex_t jas_basicmutex_t; #elif defined(JAS_THREADS_WIN32) typedef CRITICAL_SECTION jas_basicmutex_t; #endif /*! Mutex initializer. */ #if defined(JAS_THREADS_C11) #undef JAS_BASICMUTEX_INITIALIZER #elif defined(JAS_THREADS_PTHREAD) #define JAS_BASICMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #elif defined(JAS_THREADS_WIN32) #define JAS_BASICMUTEX_INITIALIZER #endif /**************************************\ * Mutex (Allowing Static Initialization) \**************************************/ #if defined(JAS_USE_SPINLOCK) # define jas_mutex_t jas_spinlock_t # define JAS_MUTEX_INITIALIZER JAS_SPINLOCK_INITIALIZER # define jas_mutex_init jas_spinlock_init # define jas_mutex_cleanup jas_spinlock_cleanup # define jas_mutex_lock jas_spinlock_lock # define jas_mutex_unlock jas_spinlock_unlock #else # define jas_mutex_t jas_basicmutex_t # define JAS_MUTEX_INITIALIZER JAS_BASICMUTEX_INITIALIZER # define jas_mutex_init jas_basicmutex_init # define jas_mutex_cleanup jas_basicmutex_cleanup # define jas_mutex_lock jas_basicmutex_lock # define jas_mutex_unlock jas_basicmutex_unlock #endif /**************************************\ * Once Flag \**************************************/ /*! Once-flag type. */ #if defined(JAS_THREADS_C11) typedef once_flag jas_once_flag_t; #elif defined(JAS_THREADS_PTHREAD) typedef pthread_once_t jas_once_flag_t; #elif defined(JAS_THREADS_WIN32) typedef struct { volatile LONG status; } jas_once_flag_t; #endif /*! Once-flag initializer. */ #if defined(JAS_THREADS_C11) # define JAS_ONCE_FLAG_INIT ONCE_FLAG_INIT #elif defined(JAS_THREADS_PTHREAD) # define JAS_ONCE_FLAG_INIT PTHREAD_ONCE_INIT #elif defined(JAS_THREADS_WIN32) # define JAS_ONCE_FLAG_INIT {0} #endif /**************************************\ * Threads \**************************************/ #if defined(JAS_FOR_INTERNAL_USE_ONLY) || defined(JAS_FOR_JASPER_APP_USE_ONLY) /*! Thread ID type. */ #if defined(JAS_THREADS_C11) typedef thrd_t jas_thread_id_t; #elif defined(JAS_THREADS_PTHREAD) typedef pthread_t jas_thread_id_t; #elif defined(JAS_THREADS_WIN32) typedef HANDLE jas_thread_id_t; #endif /*! Thread type. */ #if defined(JAS_THREADS_C11) typedef thrd_t jas_thread_t; #elif defined(JAS_THREADS_PTHREAD) typedef struct { pthread_t id; int (*func)(void *); void *arg; int result; } jas_thread_t; #elif defined(JAS_THREADS_WIN32) typedef struct { jas_thread_id_t id; int (*func)(void *); void *arg; } jas_thread_t; #endif static inline void jas_thread_yield(void); #endif /**************************************\ * Thread-Specific Storage (TSS) \**************************************/ /*! Thread-specific storage type. */ #if defined(JAS_THREADS_C11) typedef tss_t jas_tss_t; #elif defined(JAS_THREADS_PTHREAD) typedef pthread_key_t jas_tss_t; #elif defined(JAS_THREADS_WIN32) typedef DWORD jas_tss_t; #endif /******************************************************************************\ * Spinlock \******************************************************************************/ #if defined(JAS_USE_SPINLOCK) /*! @brief Initialize a spinlock. @param mtx A pointer to the spinlock to be initialized. @returns If the spinlock is successfully initialized, zero is returned. Otherwise, a nonzero value is returned. */ static inline int jas_spinlock_init(jas_spinlock_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) atomic_flag_clear(&mtx->flag); return 0; #elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1; #elif defined(JAS_THREADS_WIN32) InterlockedExchange(&mtx->flag, 0); return 0; #endif } /*! @brief Clean up a spinlock mutex. @param mtx A pointer to the spinlock to be cleaned up. @returns If the spinlock is successfully cleaned up, zero is returned. Otherwise, a nonzero value is returned. */ static inline int jas_spinlock_cleanup(jas_spinlock_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) JAS_UNUSED(mtx); return 0; #elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1; #elif defined(JAS_THREADS_WIN32) JAS_UNUSED(mtx); return 0; #endif } /*! @brief Acquire a spinlock. @param mtx A pointer to the spinlock to be acquired. @returns If successful, zero is returned. Otherwise, a nonzero value is returned. */ static inline int jas_spinlock_lock(jas_spinlock_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) while (atomic_flag_test_and_set(&mtx->flag)) {} return 0; #elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1; #elif defined(JAS_THREADS_WIN32) while (InterlockedCompareExchange(&mtx->flag, 1, 0)) {} return 0; #endif } /*! @brief Release a spinlock. @param mtx A pointer to the spinlock to be released. @returns If the operation is successful, zero is returned. Otherwise, a nonzero value is returned. */ static inline int jas_spinlock_unlock(jas_spinlock_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) atomic_flag_clear(&mtx->flag); return 0; #elif defined(JAS_THREADS_PTHREAD) JAS_UNUSED(mtx); abort(); return -1; #elif defined(JAS_THREADS_WIN32) InterlockedExchange(&mtx->flag, 0); return 0; #endif } #endif /******************************************************************************\ * Basic Mutex \******************************************************************************/ /* For internal use only. */ static inline int jas_basicmutex_init(jas_basicmutex_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) return mtx_init(mtx, mtx_plain) == thrd_success ? 0 : -1; #elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_init(mtx, 0); #elif defined(JAS_THREADS_WIN32) InitializeCriticalSection(mtx); return 0; #endif } /* For internal use only. */ static inline int jas_basicmutex_cleanup(jas_basicmutex_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) mtx_destroy(mtx); return 0; #elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_destroy(mtx); #elif defined(JAS_THREADS_WIN32) DeleteCriticalSection(mtx); return 0; #endif } /* For internal use only. */ static inline int jas_basicmutex_lock(jas_basicmutex_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) return mtx_lock(mtx); #elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_lock(mtx); #elif defined(JAS_THREADS_WIN32) EnterCriticalSection(mtx); return 0; #endif } /* For internal use only. */ static inline int jas_basicmutex_unlock(jas_basicmutex_t *mtx) { assert(mtx); #if defined(JAS_THREADS_C11) return mtx_unlock(mtx); #elif defined(JAS_THREADS_PTHREAD) return pthread_mutex_unlock(mtx); #elif defined(JAS_THREADS_WIN32) LeaveCriticalSection(mtx); return 0; #endif } /******************************************************************************\ * Thread-Specific Storage (TSS) \******************************************************************************/ /*! @brief Create thread-specific storage. @param tss A pointer to the TSS object to be initialized. @param destructor A function to be called when the TSS is deallocated when the thread exits. @returns If the operation is successful, zero is returned. Otherwise, a nonzero value is returned. */ static inline int jas_tss_create(jas_tss_t *tss, void (*destructor)(void *)) { assert(tss); #if defined(JAS_THREADS_C11) return tss_create(tss, destructor) == thrd_success ? 0 : -1; #elif defined(JAS_THREADS_PTHREAD) return pthread_key_create(tss, destructor); #elif defined(JAS_THREADS_WIN32) if (destructor) { return -1; } DWORD id; if ((id = TlsAlloc()) == TLS_OUT_OF_INDEXES) { return -2; } *tss = id; return 0; #endif } /*! @brief Delete thread-specific storage. @param tss The TSS to be destroyed. @returns If the operation is successful, zero is returned.