14#if HX_USE_MACROS_WITH_MODULE
15#error Header does not provide macros alone.
17#if (HX_USE_THREADS) != 0 && (HX_USE_THREADS) != 1 && (HX_USE_THREADS) != 11
18#error HX_USE_THREADS must be 0, 1 or 11. 11 is for using <threads.h>.
21#if (HX_USE_THREADS) == 11
38 static_assert(
sizeof(T_) <=
sizeof(
void*),
39 "hxthread_local: sizeof(T) must be <= sizeof(void*)");
44#if (HX_USE_THREADS) == 11
45 const int code_ = ::tss_create(&m_key_, 0);
46 hxassert_always(code_ == thrd_success,
"tss_create %d", code_); (void)code_;
48 const int code_ = ::pthread_key_create(&m_key_, 0);
49 hxassert_always(code_ == 0,
"pthread_key_create %s", ::strerror(code_)); (void)code_;
57#if (HX_USE_THREADS) == 11
60 ::pthread_key_delete(m_key_);
66#if (HX_USE_THREADS) == 11
67 return (T_)(intptr_t)::tss_get(m_key_);
69 return (T_)(intptr_t)::pthread_getspecific(m_key_);
77#if (HX_USE_THREADS) == 11
78 const int code_ = ::tss_set(m_key_, (
void*)(intptr_t)local_);
79 hxassert_hard(code_ == thrd_success,
"tss_set %d", code_); (void)code_;
81 const int code_ = ::pthread_setspecific(m_key_, (
void*)(intptr_t)local_);
82 hxassert_hard(code_ == 0,
"pthread_setspecific %s", ::strerror(code_)); (void)code_;
93 void operator&(
void)
const =
delete;
94 void operator&(
void) =
delete;
96#if (HX_USE_THREADS) == 11
99 ::pthread_key_t m_key_;
108#if (HX_USE_THREADS) == 11
110 return static_cast<size_t>(::thrd_current()._Tid);
112 return static_cast<size_t>(::thrd_current());
115 return static_cast<size_t>(::pthread_self());
132#if (HX_USE_THREADS) == 11
133 const int code_ = ::mtx_init(&m_mutex_, mtx_plain);
134 hxassert_always(code_ == thrd_success,
"mtx_init %d", code_); (void)code_;
136 const int code_ = ::pthread_mutex_init(&m_mutex_, 0);
137 hxassert_always(code_ == 0,
"pthread_mutex_init %s", ::strerror(code_)); (void)code_;
143#if (HX_USE_THREADS) == 11
144 ::mtx_destroy(&m_mutex_);
146 const int code_ = ::pthread_mutex_destroy(&m_mutex_);
147 hxassertf(code_ == 0,
"pthread_mutex_destroy %s", ::strerror(code_)); (void)code_;
155#if (HX_USE_THREADS) == 11
156 const int code_ = ::mtx_lock(&m_mutex_);
157 hxassertf(code_ == thrd_success,
"mtx_lock %d", code_);
158 return code_ == thrd_success;
160 const int code_ = ::pthread_mutex_lock(&m_mutex_);
161 hxassertf(code_ == 0 || code_ == EAGAIN,
"pthread_mutex_lock %s", ::strerror(code_));
170#if (HX_USE_THREADS) == 11
171 const int code_ = ::mtx_unlock(&m_mutex_);
172 hxassertf(code_ == thrd_success,
"mtx_unlock %d", code_);
173 return code_ == thrd_success;
175 const int code_ = ::pthread_mutex_unlock(&m_mutex_);
176 hxassertf(code_ == 0,
"pthread_mutex_unlock %s", ::strerror(code_));
182#if (HX_USE_THREADS) == 11
185 hxinline ::pthread_mutex_t*
native_handle(
void) {
return &m_mutex_; }
192#if (HX_USE_THREADS) == 11
195 ::pthread_mutex_t m_mutex_;
206 : m_mutex_(mtx_), m_owns_(false) {
220 m_owns_ = m_mutex_.lock();
251#if (HX_USE_THREADS) == 11
252 const int code_ = ::cnd_init(&m_cond_);
253 hxassert_always(code_ == thrd_success,
"cnd_init %d", code_); (void)code_;
255 const int code_ = ::pthread_cond_init(&m_cond_, 0);
256 hxassert_always(code_ == 0,
"pthread_cond_init %s", ::strerror(code_)); (void)code_;
262#if (HX_USE_THREADS) == 11
263 ::cnd_destroy(&m_cond_);
265 const int code_ = ::pthread_cond_destroy(&m_cond_);
266 hxassertf(code_ == 0,
"pthread_cond_destroy %s", ::strerror(code_)); (void)code_;
275#if (HX_USE_THREADS) == 11
276 const int code_ = ::cnd_wait(&m_cond_, mutex_.
native_handle());
277 hxassertf(code_ == thrd_success,
"cnd_wait %d", code_);
278 return code_ == thrd_success;
280 const int code_ = ::pthread_cond_wait(&m_cond_, mutex_.
native_handle());
281 hxassertf(code_ == 0,
"pthread_cond_wait %s", ::strerror(code_));
295 template<
typename callable_t_>
297 while(!callable_()) {
299 const bool wait_result_ = this->
wait(lock_);
300 hxassertf(wait_result_,
"wait"); (void)wait_result_;
306#if (HX_USE_THREADS) == 11
307 const int code_ = ::cnd_signal(&m_cond_);
308 hxassertf(code_ == thrd_success,
"cnd_signal %d", code_);
309 return code_ == thrd_success;
311 const int code_ = ::pthread_cond_signal(&m_cond_);
312 hxassertf(code_ == 0,
"pthread_cond_signal %s", ::strerror(code_));
319#if (HX_USE_THREADS) == 11
320 const int code_ = ::cnd_broadcast(&m_cond_);
321 hxassertf(code_ == thrd_success,
"cnd_broadcast %d", code_);
322 return code_ == thrd_success;
324 const int code_ = ::pthread_cond_broadcast(&m_cond_);
325 hxassertf(code_ == 0,
"pthread_cond_broadcast %s", ::strerror(code_));
331#if (HX_USE_THREADS) == 11
334 hxinline ::pthread_cond_t*
native_handle(
void) {
return &m_cond_; }
341#if (HX_USE_THREADS) == 11
344 ::pthread_cond_t m_cond_;
352#if (HX_USE_THREADS) == 11
369 template<
typename parameter_t_>
372 this->
start(entry_point_, parameter_);
386 template<
typename parameter_t_>
393 static_assert(
sizeof(
void*) ==
sizeof(parameter_t_*),
"Incompatible pointer sizes");
395 void* reinterpreted_parameter_ =
hxnull;
396 ::memcpy(&reinterpreted_parameter_, ¶meter_,
sizeof(
void*));
397#if (HX_USE_THREADS) == 11
398 const int code_ = ::thrd_create(&m_thread_,
399 reinterpret_cast<entry_point_function_t_
>(entry_point_), reinterpreted_parameter_);
400 hxassert_always(code_ == thrd_success,
"thrd_create %d", code_); (void)code_;
402 const int code_ = ::pthread_create(&m_thread_, 0,
403 reinterpret_cast<entry_point_function_t_
>(entry_point_), reinterpreted_parameter_);
404 hxassert_always(code_ == 0,
"pthread_create %s", ::strerror(code_)); (void)code_;
416#if (HX_USE_THREADS) == 11
417 const int code_ = ::thrd_join(m_thread_,
hxnull);
421 const int code_ = ::pthread_join(m_thread_, 0);
429 using entry_point_function_t_ =
return_t (*)(
void*);
434#if (HX_USE_THREADS) == 11
437 ::pthread_t m_thread_;
hxcondition_variable(void)
Constructs and initializes the condition variable.
Definition hxthread.hpp:250
bool notify_one(void)
Notifies one waiting thread. Returns true on success, false otherwise.
Definition hxthread.hpp:305
bool notify_all(void)
Notifies all waiting threads. Returns true on success, false otherwise.
Definition hxthread.hpp:318
inline::cnd_t * native_handle(void)
Returns a pointer to the native condition variable handle.
Definition hxthread.hpp:332
~hxcondition_variable(void)
Destroys the condition variable if valid.
Definition hxthread.hpp:261
bool wait(hxunique_lock &lock_)
Overload accepting a hxunique_lock in place of a hxmutex.
Definition hxthread.hpp:288
void wait(hxunique_lock &lock_, callable_t_ &&callable_)
Waits until the predicate returns true.
Definition hxthread.hpp:296
bool wait(hxmutex &mutex_)
Waits for the condition variable to be notified.
Definition hxthread.hpp:274
hxmutex - std::mutex style wrapper for the configured threading backend.
Definition hxthread.hpp:127
bool lock(void)
Locks the mutex.
Definition hxthread.hpp:154
bool unlock(void)
Unlocks the mutex.
Definition hxthread.hpp:169
hxmutex(void)
Constructs a mutex and initializes it.
Definition hxthread.hpp:131
~hxmutex(void)
Destroys the mutex.
Definition hxthread.hpp:142
inline::mtx_t * native_handle(void)
Returns a pointer to the native mutex handle.
Definition hxthread.hpp:183
hxthread_local - Provides thread-local storage for an integer or a pointer.
Definition hxthread.hpp:37
hxthread_local(void)
Construct to 0 or null.
Definition hxthread.hpp:43
void operator=(T local_)
Sets the thread-local value. This is a form of "mutable when const.".
Definition hxthread.hpp:76
~hxthread_local()
Frees resources.
Definition hxthread.hpp:56
hxthread - std::thread style thread wrapper for the configured backend.
Definition hxthread.hpp:350
hxthread(void)
Default constructor. Thread is not started.
Definition hxthread.hpp:361
hxthread(return_t(*entry_point_)(parameter_t_ *), parameter_t_ *parameter_)
Constructs and starts a thread with the given function and argument.
Definition hxthread.hpp:370
void start(return_t(*entry_point_)(parameter_t_ *), parameter_t_ *parameter_)
Starts a thread with the given function and argument.
Definition hxthread.hpp:387
bool joinable(void) const
Returns true if the thread has been started and not yet joined.
Definition hxthread.hpp:411
int return_t
The return type of a thread entry point as required by the configured backend.
Definition hxthread.hpp:355
~hxthread(void)
Destructor. Asserts that the thread was stopped correctly.
Definition hxthread.hpp:376
void join(void)
Joins the thread. Blocks until the thread finishes.
Definition hxthread.hpp:414
hxunique_lock - std::unique_lock style RAII-style unique lock for hxmutex.
Definition hxthread.hpp:201
bool owns_lock(void) const
Returns true if the lock owns the mutex.
Definition hxthread.hpp:232
void lock(void)
Locks the mutex if not already locked.
Definition hxthread.hpp:218
hxunique_lock(hxmutex &mtx_, bool defer_lock_=false)
Constructs with an option to defer locking.
Definition hxthread.hpp:205
hxmutex & mutex(void)
Returns a reference to the associated mutex.
Definition hxthread.hpp:235
~hxunique_lock(void)
Unlocks the mutex if owned.
Definition hxthread.hpp:212
void unlock(void)
Unlocks the mutex if owned.
Definition hxthread.hpp:224
#define hxinline
hxinline - Force a function to be inlined into its callers.
Definition hxsettings.h:125
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:98
#define hxattr_flatten
hxattr_flatten - Inline every call inside a function's body into it, recursively, regardless of the c...
Definition hxsettings.h:90
size_t hxthread_id(void)
hxthread_id - Returns the current thread ID.
Definition hxthread.hpp:107
A few utility functions and most standard C++ meta programming functions.
Provides core macros, memory management and feature detection.
#define hxassertf(x_,...)
hxassertf(bool x, ...) - Logs an error and terminates execution if x is false.
Definition libhatchet.h:101
#define hxnull
hxnull - The null pointer value for a given pointer type represented by the numeric literal 0.
Definition libhatchet.h:280
#define hxassert_always(x_,...)
hxassert_always(bool x, ...) - Logs an error and terminates execution if x is false.
Definition libhatchet.h:121
#define hxassert_hard(x_,...)
hxassert_hard(bool x, ...) - Logs an error and terminates execution if x is false.
Definition libhatchet.h:111