diff options
Diffstat (limited to 'source/kit/threads.h')
-rw-r--r-- | source/kit/threads.h | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/source/kit/threads.h b/source/kit/threads.h new file mode 100644 index 0000000..d98978d --- /dev/null +++ b/source/kit/threads.h @@ -0,0 +1,201 @@ +/* + * C11 <threads.h> emulation library + * + * (C) Copyright yohhoy 2012. + * Copyright 2022 Yonggang Luo + * Distributed under the Boost Software License, Version 1.0. + * + * Permission is hereby granted, free of charge, to any person or + * organization obtaining a copy of the software and accompanying + * documentation covered by this license (the "Software") to use, + * reproduce, display, distribute, execute, and transmit the Software, + * and to prepare [[derivative work]]s of the Software, and to permit + * third-parties to whom the Software is furnished to do so, all + * subject to the following: + * + * The copyright notices in the Software and this entire statement, + * including the above license grant, this restriction and the + * following disclaimer, must be included in all copies of the + * Software, in whole or in part, and all derivative works of the + * Software, unless such copies or derivative works are solely in the + * form of machine-executable object code generated by a source + * language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE + * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER + * LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef KIT_THREADS_H +#define KIT_THREADS_H + +#ifndef KIT_DISABLE_SYSTEM_THREADS +# include "time.h" + +# include <errno.h> +# include <limits.h> +# include <stdlib.h> + +# ifdef _MSC_VER +# define _Noreturn __declspec(noreturn) +# endif + +# if defined(_WIN32) && !defined(__CYGWIN__) +# include <io.h> /* close */ +# include <process.h> /* _exit */ +# elif defined(KIT_HAVE_PTHREAD) +# include <pthread.h> +# include <unistd.h> /* close, _exit */ +# else +# error Not supported on this platform. +# endif + +/*---------------------------- macros ---------------------------*/ + +# ifndef _Thread_local +# if defined(__cplusplus) +/* C++11 doesn't need `_Thread_local` keyword or macro */ +# elif !defined(__STDC_NO_THREADS__) +/* threads are optional in C11, _Thread_local present in this + * condition */ +# elif defined(_MSC_VER) +# define _Thread_local __declspec(thread) +# elif defined(__GNUC__) +# define _Thread_local __thread +# else +/* Leave _Thread_local undefined so that use of _Thread_local would + * not promote to a non-thread-local global variable + */ +# endif +# endif + +# if !defined(__cplusplus) +/* + * C11 thread_local() macro + * C++11 and above already have thread_local keyword + */ +# ifndef thread_local +# if _MSC_VER +# define thread_local __declspec(thread) +# else +# define thread_local _Thread_local +# endif +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +/*---------------------------- types ----------------------------*/ +typedef void (*tss_dtor_t)(void *); +typedef int (*thrd_start_t)(void *); + +# if defined(_WIN32) && !defined(__CYGWIN__) +typedef struct { + void *Ptr; +} cnd_t; +/* Define thrd_t as struct type intentionally for avoid use of thrd_t + * as pointer type */ +typedef struct { + void *handle; +} thrd_t; +typedef unsigned long tss_t; +typedef struct { + void *DebugInfo; + long LockCount; + long RecursionCount; + void *OwningThread; + void *LockSemaphore; + uintptr_t SpinCount; +} mtx_t; /* Mock of CRITICAL_SECTION */ +typedef struct { + volatile uintptr_t status; +} once_flag; +// FIXME: temporary non-standard hack to ease transition +# define KIT_MTX_INITIALIZER_NP_ \ + { (void *) -1, -1, 0, 0, 0, 0 } +# define ONCE_FLAG_INIT \ + { 0 } +# define TSS_DTOR_ITERATIONS 1 +# elif defined(KIT_HAVE_PTHREAD) +typedef pthread_cond_t cnd_t; +typedef pthread_t thrd_t; +typedef pthread_key_t tss_t; +typedef pthread_mutex_t mtx_t; +typedef pthread_once_t once_flag; +// FIXME: temporary non-standard hack to ease transition +# define KIT_MTX_INITIALIZER_NP_ PTHREAD_MUTEX_INITIALIZER +# define ONCE_FLAG_INIT PTHREAD_ONCE_INIT +# ifdef PTHREAD_DESTRUCTOR_ITERATIONS +# define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS +# else +# define TSS_DTOR_ITERATIONS \ + 1 // assume TSS dtor MAY be called at least once. +# endif +# else +# error Not supported on this platform. +# endif + +/*-------------------- enumeration constants --------------------*/ +enum { + mtx_plain = 0, + mtx_recursive = 1, + mtx_timed = 2, +}; + +enum { + thrd_success = 0, // succeeded + thrd_timedout, // timed out + thrd_error, // failed + thrd_busy, // resource busy + thrd_nomem // out of memory +}; + +/*-------------------------- functions --------------------------*/ + +void call_once(once_flag *, void (*)(void)); +int cnd_broadcast(cnd_t *); +void cnd_destroy(cnd_t *); +int cnd_init(cnd_t *); +int cnd_signal(cnd_t *); +int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict mtx_, + const struct timespec *__restrict); +int cnd_wait(cnd_t *, mtx_t *mtx_); +void mtx_destroy(mtx_t *mtx_); +int mtx_init(mtx_t *mtx_, int); +int mtx_lock(mtx_t *mtx_); +int mtx_timedlock(mtx_t *__restrict mtx_, + const struct timespec *__restrict); +int mtx_trylock(mtx_t *mtx_); +int mtx_unlock(mtx_t *mtx_); +int thrd_create(thrd_t *, thrd_start_t, void *); +thrd_t thrd_current(void); +int thrd_detach(thrd_t); +int thrd_equal(thrd_t, thrd_t); +# if defined(__cplusplus) +[[ noreturn ]] +# else +_Noreturn +# endif +void thrd_exit(int); +int thrd_join(thrd_t, int *); +int thrd_sleep(const struct timespec *, struct timespec *); +void thrd_yield(void); +int tss_create(tss_t *, tss_dtor_t); +void tss_delete(tss_t); +void *tss_get(tss_t); +int tss_set(tss_t, void *); + +# ifdef __cplusplus +} +# endif + +#endif /* KIT_DISABLE_SYSTEM_THREADS */ + +#endif /* KIT_THREADS_H */ |