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*),
"hxthread_local: sizeof(T) must be <= sizeof(void*)");
43#if (HX_USE_THREADS) == 11
44 const int code_ = ::tss_create(&m_key_, 0);
45 hxassert_always(code_ == thrd_success,
"tss_create %d", code_); (void)code_;
47 const int code_ = ::pthread_key_create(&m_key_, 0);
48 hxassert_always(code_ == 0,
"pthread_key_create %s", ::strerror(code_)); (void)code_;
56#if (HX_USE_THREADS) == 11
59 ::pthread_key_delete(m_key_);
65#if (HX_USE_THREADS) == 11
66 return (T_)(intptr_t)::tss_get(m_key_);
68 return (T_)(intptr_t)::pthread_getspecific(m_key_);
76#if (HX_USE_THREADS) == 11
77 const int code_ = ::tss_set(m_key_, (
void*)(intptr_t)local_);
78 hxassert_hard(code_ == thrd_success,
"tss_set %d", code_); (void)code_;
80 const int code_ = ::pthread_setspecific(m_key_, (
void*)(intptr_t)local_);
81 hxassert_hard(code_ == 0,
"pthread_setspecific %s", ::strerror(code_)); (void)code_;
92 void operator&(
void)
const =
delete;
93 void operator&(
void) =
delete;
95#if (HX_USE_THREADS) == 11
98 ::pthread_key_t m_key_;
107#if (HX_USE_THREADS) == 11
109 return static_cast<size_t>(::thrd_current()._Tid);
111 return static_cast<size_t>(::thrd_current());
114 return static_cast<size_t>(::pthread_self());
131#if (HX_USE_THREADS) == 11
132 const int code_ = ::mtx_init(&m_mutex_, mtx_plain);
133 hxassert_always(code_ == thrd_success,
"mtx_init %d", code_); (void)code_;
135 const int code_ = ::pthread_mutex_init(&m_mutex_, 0);
136 hxassert_always(code_ == 0,
"pthread_mutex_init %s", ::strerror(code_)); (void)code_;
142#if (HX_USE_THREADS) == 11
143 ::mtx_destroy(&m_mutex_);
145 const int code_ = ::pthread_mutex_destroy(&m_mutex_);
146 hxassertmsg(code_ == 0,
"pthread_mutex_destroy %s", ::strerror(code_)); (void)code_;
154#if (HX_USE_THREADS) == 11
155 const int code_ = ::mtx_lock(&m_mutex_);
156 hxassertmsg(code_ == thrd_success,
"mtx_lock %d", code_);
157 return code_ == thrd_success;
159 const int code_ = ::pthread_mutex_lock(&m_mutex_);
160 hxassertmsg(code_ == 0 || code_ == EAGAIN,
"pthread_mutex_lock %s", ::strerror(code_));
169#if (HX_USE_THREADS) == 11
170 const int code_ = ::mtx_unlock(&m_mutex_);
171 hxassertmsg(code_ == thrd_success,
"mtx_unlock %d", code_);
172 return code_ == thrd_success;
174 const int code_ = ::pthread_mutex_unlock(&m_mutex_);
175 hxassertmsg(code_ == 0,
"pthread_mutex_unlock %s", ::strerror(code_));
181#if (HX_USE_THREADS) == 11
184 hxinline ::pthread_mutex_t*
native_handle(
void) {
return &m_mutex_; }
191#if (HX_USE_THREADS) == 11
194 ::pthread_mutex_t m_mutex_;
205 : m_mutex_(mtx_), m_owns_(false) {
219 m_owns_ = m_mutex_.lock();
250#if (HX_USE_THREADS) == 11
251 const int code_ = ::cnd_init(&m_cond_);
252 hxassert_always(code_ == thrd_success,
"cnd_init %d", code_); (void)code_;
254 const int code_ = ::pthread_cond_init(&m_cond_, 0);
255 hxassert_always(code_ == 0,
"pthread_cond_init %s", ::strerror(code_)); (void)code_;
261#if (HX_USE_THREADS) == 11
262 ::cnd_destroy(&m_cond_);
264 const int code_ = ::pthread_cond_destroy(&m_cond_);
265 hxassertmsg(code_ == 0,
"pthread_cond_destroy %s", ::strerror(code_)); (void)code_;
274#if (HX_USE_THREADS) == 11
275 const int code_ = ::cnd_wait(&m_cond_, mutex_.
native_handle());
276 hxassertmsg(code_ == thrd_success,
"cnd_wait %d", code_);
277 return code_ == thrd_success;
279 const int code_ = ::pthread_cond_wait(&m_cond_, mutex_.
native_handle());
280 hxassertmsg(code_ == 0,
"pthread_cond_wait %s", ::strerror(code_));
296 template<
typename callable_t_>
298 while(!callable_()) {
300 const bool wait_result_ = this->
wait(lock_);
301 hxassertmsg(wait_result_,
"wait"); (void)wait_result_;
307#if (HX_USE_THREADS) == 11
308 const int code_ = ::cnd_signal(&m_cond_);
309 hxassertmsg(code_ == thrd_success,
"cnd_signal %d", code_);
310 return code_ == thrd_success;
312 const int code_ = ::pthread_cond_signal(&m_cond_);
313 hxassertmsg(code_ == 0,
"pthread_cond_signal %s", ::strerror(code_));
320#if (HX_USE_THREADS) == 11
321 const int code_ = ::cnd_broadcast(&m_cond_);
322 hxassertmsg(code_ == thrd_success,
"cnd_broadcast %d", code_);
323 return code_ == thrd_success;
325 const int code_ = ::pthread_cond_broadcast(&m_cond_);
326 hxassertmsg(code_ == 0,
"pthread_cond_broadcast %s", ::strerror(code_));
332#if (HX_USE_THREADS) == 11
335 hxinline ::pthread_cond_t*
native_handle(
void) {
return &m_cond_; }
342#if (HX_USE_THREADS) == 11
345 ::pthread_cond_t m_cond_;
353#if (HX_USE_THREADS) == 11
370 template<
typename parameter_t_>
373 this->
start(entry_point_, parameter_);
387 template<
typename parameter_t_>
394 static_assert(
sizeof(
void*) ==
sizeof(parameter_t_*),
"Incompatible pointer sizes");
396 void* reinterpreted_parameter_ =
hxnull;
397 ::memcpy(&reinterpreted_parameter_, ¶meter_,
sizeof(
void*));
398#if (HX_USE_THREADS) == 11
399 const int code_ = ::thrd_create(&m_thread_,
400 reinterpret_cast<entry_point_function_t_
>(entry_point_), reinterpreted_parameter_);
401 hxassert_always(code_ == thrd_success,
"thrd_create %d", code_); (void)code_;
403 const int code_ = ::pthread_create(&m_thread_, 0,
404 reinterpret_cast<entry_point_function_t_
>(entry_point_), reinterpreted_parameter_);
405 hxassert_always(code_ == 0,
"pthread_create %s", ::strerror(code_)); (void)code_;
417#if (HX_USE_THREADS) == 11
418 const int code_ = ::thrd_join(m_thread_,
hxnull);
422 const int code_ = ::pthread_join(m_thread_, 0);
430 using entry_point_function_t_ =
return_t (*)(
void*);
435#if (HX_USE_THREADS) == 11
438 ::pthread_t m_thread_;
hxcondition_variable(void)
Constructs and initializes the condition variable.
Definition hxthread.hpp:249
bool notify_one(void)
Notifies one waiting thread. Returns true on success, false otherwise.
Definition hxthread.hpp:306
bool notify_all(void)
Notifies all waiting threads. Returns true on success, false otherwise.
Definition hxthread.hpp:319
inline::cnd_t * native_handle(void)
Returns a pointer to the native condition variable handle.
Definition hxthread.hpp:333
~hxcondition_variable(void)
Destroys the condition variable if valid.
Definition hxthread.hpp:260
bool wait(hxunique_lock &lock_)
Overload: Waits using a hxunique_lock.
Definition hxthread.hpp:289
void wait(hxunique_lock &lock_, callable_t_ &&callable_)
Waits until the predicate returns true.
Definition hxthread.hpp:297
bool wait(hxmutex &mutex_)
Waits for the condition variable to be notified.
Definition hxthread.hpp:273
hxmutex - std::mutex style wrapper for the configured threading backend.
Definition hxthread.hpp:126
bool lock(void)
Locks the mutex.
Definition hxthread.hpp:153
bool unlock(void)
Unlocks the mutex.
Definition hxthread.hpp:168
hxmutex(void)
Constructs a mutex and initializes it.
Definition hxthread.hpp:130
~hxmutex(void)
Destroys the mutex.
Definition hxthread.hpp:141
inline::mtx_t * native_handle(void)
Returns a pointer to the native mutex handle.
Definition hxthread.hpp:182
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:42
void operator=(T local_)
Sets the thread-local value. This is a form of "mutable when const.".
Definition hxthread.hpp:75
~hxthread_local()
Frees resources.
Definition hxthread.hpp:55
hxthread - std::thread style thread wrapper for the configured backend.
Definition hxthread.hpp:351
hxthread(void)
Default constructor. Thread is not started.
Definition hxthread.hpp:362
hxthread(return_t(*entry_point_)(parameter_t_ *), parameter_t_ *parameter_)
Constructs and starts a thread with the given function and argument.
Definition hxthread.hpp:371
void start(return_t(*entry_point_)(parameter_t_ *), parameter_t_ *parameter_)
Starts a thread with the given function and argument.
Definition hxthread.hpp:388
bool joinable(void) const
Returns true if the thread has been started and not yet joined.
Definition hxthread.hpp:412
int return_t
The return type of a thread entry point as required by the configured backend.
Definition hxthread.hpp:356
~hxthread(void)
Destructor. Asserts that the thread was stopped correctly.
Definition hxthread.hpp:377
void join(void)
Joins the thread. Blocks until the thread finishes.
Definition hxthread.hpp:415
hxunique_lock - std::unique_lock style RAII-style unique lock for hxmutex.
Definition hxthread.hpp:200
bool owns_lock(void) const
Returns true if the lock owns the mutex.
Definition hxthread.hpp:231
void lock(void)
Locks the mutex if not already locked.
Definition hxthread.hpp:217
hxunique_lock(hxmutex &mtx_, bool defer_lock_=false)
Constructs with an option to defer locking.
Definition hxthread.hpp:204
hxmutex & mutex(void)
Returns a reference to the associated mutex.
Definition hxthread.hpp:234
~hxunique_lock(void)
Unlocks the mutex if owned.
Definition hxthread.hpp:211
void unlock(void)
Unlocks the mutex if owned.
Definition hxthread.hpp:223
#define hxinline
hxinline - Force a function to be inlined into its callers.
Definition hxsettings.h:120
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:89
#define hxattr_flatten
hxattr_flatten - Inline every call inside a function's body into it, recursively, regardless of the c...
Definition hxsettings.h:82
size_t hxthread_id(void)
hxthread_id - Returns the current thread ID.
Definition hxthread.hpp:106
A few utility functions and most standard C++ meta programming functions.
Provides core macros, memory management and feature detection.
#define hxassertmsg(x_,...)
hxassertmsg(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 constant 0.
Definition libhatchet.h:277
#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