// Copyright 2012-2020 David Robillard // SPDX-License-Identifier: ISC #ifndef ZIX_THREAD_H #define ZIX_THREAD_H #include "zix/common.h" #ifdef _WIN32 # include #else # include # include #endif #include #ifdef __cplusplus extern "C" { #endif /** @addtogroup zix @{ @name Thread @{ */ #ifdef _WIN32 typedef HANDLE ZixThread; #else typedef pthread_t ZixThread; #endif /** Initialize `thread` to a new thread. The thread will immediately be launched, calling `function` with `arg` as the only parameter. */ static inline ZixStatus zix_thread_create(ZixThread* thread, size_t stack_size, void* (*function)(void*), void* arg); /** Join `thread` (block until `thread` exits). */ static inline ZixStatus zix_thread_join(ZixThread thread, void** retval); #ifdef _WIN32 static inline ZixStatus zix_thread_create(ZixThread* thread, size_t stack_size, void* (*function)(void*), void* arg) { *thread = CreateThread( NULL, stack_size, (LPTHREAD_START_ROUTINE)function, arg, 0, NULL); return *thread ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; } static inline ZixStatus zix_thread_join(ZixThread thread, void** retval) { (void)retval; return WaitForSingleObject(thread, INFINITE) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; } #else /* !defined(_WIN32) */ static inline ZixStatus zix_thread_create(ZixThread* thread, size_t stack_size, void* (*function)(void*), void* arg) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, stack_size); const int ret = pthread_create(thread, NULL, function, arg); pthread_attr_destroy(&attr); switch (ret) { case EAGAIN: return ZIX_STATUS_NO_MEM; case EINVAL: return ZIX_STATUS_BAD_ARG; case EPERM: return ZIX_STATUS_BAD_PERMS; } return ret ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; } static inline ZixStatus zix_thread_join(ZixThread thread, void** retval) { return pthread_join(thread, retval) ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; } #endif /** @} @} */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* ZIX_THREAD_H */