Threading and Synchronization Primitives module
Cnx provides a set of cross-platform multithreading and synchronization facilities to make working with concurrent code as simple and straightforward as possible. The API is similar to C++'s and that added by the C11 standard, but is supported on platforms and compilers where implementations of C11's threading may not be available (like Windows, for example).
Example:
#include <Cnx/Thread.h> #include <Cnx/IO.h> #include <Cnx/Atomic.h> #include <Cnx/Assert.h> // A lambda that captures a `CnxBasicMutex*`, two `i32*`s and an `atomic_bool`* void LambdaFunction(example_print, void) { let bindings = LambdaBinding(CnxBasicMutex*, i32*, i32*, atomic_bool*); // run until the exit flag is set let exit_flag_ptr = bindings._4; while(!atomic_load(exit_flag_ptr)) { let_mut mutex_ptr = bindings._1; let locked = cnx_basic_mutex_lock(mutex_ptr); cnx_assert(cnx_result_is_ok(locked), "Failed to lock the mutex"); if(cnx_result_is_ok(locked)) { let num1 = *(bindings._2); let num2 = *(bindings._3); println("Values: [{}, {}]", num1, num2); } } } // A lambda that captures a `CnxBasicMutex*`, two `i32*`s and an `atomic_bool`* void LambdaFunction(example_add, void) { let bindings = LambdaBinding(CnxBasicMutex*, i32*, i32*, atomic_bool*); // run until the exit flag is set let exit_flag_ptr = bindings._4; while(!atomic_load(exit_flag_ptr)) { let_mut mutex_ptr = bindings._1; let locked = cnx_basic_mutex_lock(mutex_ptr); // cnx_assert(cnx_result_is_ok(locked), "Failed to lock the mutex"); if(cnx_result_is_ok(locked)) { let_mut num1_ptr = bindings._2; let_mut num2_ptr = bindings._3; (*(num1_ptr))++; (*(num2_ptr))++; } } } // Spawns one thread that continuosly prints two `i32`s for 60 seconds. // Spawns a second thread that continuously increments said `i32`s. // After 60 seconds, joins both threads. void example(void) { i32 val1 = 0; i32 val2 = 0; atomic_bool exit_flag = false; let_mut maybe_mutex = cnx_basic_mutex_new(); cnx_assert(cnx_result_is_ok(maybe_mutex), "Failed to create a new mutex"); let_mut mutex = cnx_result_unwrap(maybe_mutex); // creates a new thread whose startup routine is the `LambdaFunction` `example_print` // the lambda will be automatically freed when the thread completes execution let_mut maybe_print_thread = cnx_thread_new(lambda(example_print, &mutex, &val1, &val2, &exit_flag)); cnx_assert(cnx_result_is_ok(maybe_print_thread), "Failed to create print thread"); let_mut print_thread = cnx_result_unwrap(maybe_print_thread); // creates a new thread whose startup routine is the `LambdaFunction` `example_add` // the lambda will be automatically freed when the thread completes execution let_mut maybe_add_thread = cnx_thread_new(lambda(example_add, &mutex, &val1, &val2, &exit_flag)); cnx_assert(cnx_result_is_ok(maybe_add_thread), "Failed to create add thread"); let_mut add_thread = cnx_result_unwrap(maybe_add_thread); cnx_this_thread_sleep_for(cnx_seconds(60)); atomic_store(&exit_flag, true); let print_joined = cnx_thread_join(&print_thread); let add_joined = cnx_thread_join(&add_thread); cnx_assert(cnx_result_is_ok(print_joined), "Print thread failed to join"); cnx_assert(cnx_result_is_ok(add_joined), "Adding thread failed to join"); cnx_basic_mutex_free(&mutex); println("Finshed printing the numbers!"); }
Classes
- struct CnxJThread
- A
CnxJThreadis the handle type for OS-level threads which are automatically joined when their handle goes out of scope and use a dedicated stop token to signal to the thread when its execution should end.
Typedefs
- using CnxBasicMutex = __cnx_basic_mutex
CnxBasicMutexis the basic mutual exclusion object type provided by Cnx's threading and synchronization API. Using aCnxBasicMutexto control access to shared resources will ensure that all access is synchronized and mutually exclusive between threads.- using CnxRecursiveBasicMutex = __cnx_recursive_basic_mutex
CnxRecursiveBasicMutexis the basic reentrant mutual exclusion object type provided by Cnx's threading and synchronization API. Using aCnxRecursiveBasicMutexto control access to shared resources will ensure that all access is synchronized and mutually exclusive between threads, and allows for rentrant ownership of the lock on that access.- using CnxBasicCondvar = __cnx_condvar
CnxBasicCondvaris the Condition Variable object type provided by Cnx's threading and synchronization API. Using aCnxBasicCondvarallows to block one or more threads until an event is triggered, without wasting CPU resources.- using CnxThreadID = __cnx_thread_id
- A
CnxThreadIDuniquely identifies an indiviual thread. - using CnxThread = __cnx_thread
- A
CnxThreadis the handle type for basic OS-level threads provided by Cnx's threading and synchronization API.CnxThreadprovides the facilities for creating multiple threads and ending their execution, enabling concurrent tasks and operations to be performed. - using CnxStopToken = atomic_bool
- A
CnxStopTokenis associated with aCnxJThreadand is used to signal to it when it should end its execution. - using CnxTLSKey = __cnx_tls_key
- A
CnxTLSKeyis the key type for creating, accessing, and modifying a thread-local storage object. - using CnxOnceFlag = __cnx_exec_once_flag
- A
CnxOnceFlagis a synchronization flag type for use withcnx_execute_onceto ensure a given function is executed exactly once, regardless of how many threads attempt to call it, as long as all threads do so through the sameCnxOnceFlagandcnx_execute_once
Functions
- CnxResult(CnxBasicMutex)
- Creates a new mutex.
- CnxResult cnx_basic_mutex_init(CnxBasicMutex*restrict mutex)
- Initializes the mutex pointed to by
mutex - CnxResult cnx_basic_mutex_lock(CnxBasicMutex*restrict mutex)
- Unconditionally locks the mutex pointed to by
mutex - bool cnx_basic_mutex_try_lock(CnxBasicMutex*restrict mutex)
- Attempts to lock the mutex pointed to by
mutex - CnxResult cnx_basic_mutex_unlock(CnxBasicMutex*restrict mutex)
- Unlocks the mutex pointed to by
mutex - CnxResult cnx_basic_mutex_free(CnxBasicMutex*restrict mutex)
- Destroys the mutex pointed to by
mutex - CnxResult(CnxRecursiveBasicMutex)
- Creates a new recursive mutex.
- CnxResult cnx_recursive_basic_mutex_init(CnxRecursiveBasicMutex*restrict mutex)
- Initializes the recursive mutex pointed to by
mutex - CnxResult cnx_recursive_basic_mutex_lock(CnxRecursiveBasicMutex*restrict mutex)
- Unconditionally locks the recursive mutex pointed to by
mutex - bool cnx_recursive_basic_mutex_try_lock(CnxRecursiveBasicMutex*restrict mutex)
- Attempts to lock the recursive mutex pointed to by
mutex - CnxResult cnx_recursive_basic_mutex_unlock(CnxRecursiveBasicMutex*restrict mutex)
- Unlocks the recursive mutex pointed to by
mutex - CnxResult cnx_recursive_basic_mutex_free(CnxRecursiveBasicMutex*restrict mutex)
- Destroys the recursive mutex pointed to by
mutex - CnxResult(CnxBasicCondvar)
- Creates a new condition variable, returning the result in a
CnxResult - CnxResult cnx_basic_condvar_init(CnxBasicCondvar*restrict condvar)
- Initializes the condition variable pointed to by
condvar - CnxResult cnx_basic_condvar_signal(CnxBasicCondvar*restrict condvar)
- Signals to the first thread waiting on the condition variable pointed to by
condvarto wake and continue execution. - CnxResult cnx_basic_condvar_broadcast(CnxBasicCondvar*restrict condvar)
- Signals to every thread waiting on the condition variable pointed to by
condvarto wake and continue execution. - CnxResult cnx_basic_condvar_wait(CnxBasicCondvar*restrict condvar, CnxBasicMutex*restrict mutex)
- Blocks on the condition variable pointed to by
condvaruntil the thread is signalled by it. - CnxResult cnx_basic_condvar_wait_for(CnxBasicCondvar*restrict condvar, CnxBasicMutex*restrict mutex, CnxDuration to_wait) cnx_disable_if(!mutex
- Blocks on the condition variable pointed to by
condvaruntil the thread is signalled by it, orto_waittime has elapsed. - CnxResult cnx_basic_condvar_wait_until(CnxBasicCondvar*restrict condvar, CnxBasicMutex*restrict mutex, CnxTimePoint stop_point) cnx_disable_if(!mutex
- Blocks on the condition variable pointed to by
condvaruntil the thread is signalled by it, or the point in time indicated bystop_pointtime has been reached. - CnxResult cnx_basic_condvar_free(CnxBasicCondvar*restrict condvar)
- Destroys the condition variable pointed to by
condvar - CnxResult cnx_execute_once(CnxOnceFlag*restrict flag, void(*)(void) function) cnx_disable_if(!flag
- Executes the given function exactly once.
- CnxCompare cnx_thread_id_compare(CnxThreadID lhs, CnxThreadID rhs)
- Compares the two
CnxThreadIDs. - bool cnx_thread_id_equal(CnxThreadID lhs, CnxThreadID rhs)
- Returns whether the two
CnxThreadIDs are equal. - bool cnx_thread_id_less_than(CnxThreadID lhs, CnxThreadID rhs)
- Returns whether the first
CnxThreadIDis less than the second. - bool cnx_thread_id_less_than_or_equal(CnxThreadID lhs, CnxThreadID rhs)
- Returns whether the first
CnxThreadIDis less than or equal to the second. - bool cnx_thread_id_greater_than(CnxThreadID lhs, CnxThreadID rhs)
- Returns whether the first
CnxThreadIDis greater than the second. - bool cnx_thread_id_greater_than_or_equal(CnxThreadID lhs, CnxThreadID rhs)
- Returns whether the first
CnxThreadIDis greater than or equal to the second. - typedef Lambda(void) CnxThreadLambda
- When spawning a new thread, a
Lambda(void)is used as its startup routine. This typedef allows for receiving that startup routine as a function parameter. - CnxResult(CnxThread)
- Spawns a new thread, with the given
CnxThreadLambdaas its startup routine. - CnxResult cnx_thread_init(CnxThread*restrict thread, CnxThreadLambda lambda)
- Spawns a new thread, with the given
CnxThreadLambdaas its startup routine. - bool cnx_thread_is_null(const CnxThread*restrict thread)
- Checks if the given thread handle is null (if it has been initialized)
- CnxThreadID cnx_thread_get_id(const CnxThread*restrict thread)
- Gets the ID of the current thread.
- CnxResult cnx_thread_join(CnxThread*restrict thread)
- Joins the given thread, blocking until its execution has completed.
- CnxResult cnx_thread_detach(CnxThread*restrict thread)
- Separates execution of the thread associated with the given thread handle from the handle.
- void cnx_thread_free(void* thread)
- Frees the given thread, blocking until it's joined or joining fails.
- void cnx_this_thread_yield(void)
- Yields execution of the current thread, allowing the operating system to execute other threads until it decides to return execution to this one.
- void cnx_this_thread_sleep_for(CnxDuration duration)
- Yields execution of the current thread until at least the given
durationof time has passed. - CnxThreadID cnx_this_thread_get_id(void)
- Returns the ID of the current thread.
- void cnx_stop_token_request_stop(CnxStopToken*restrict token)
- Requests the thread associated with the given stop token to end execution.
- bool cnx_stop_token_stop_requested(const CnxStopToken*restrict token)
- Returns whether the thread associated with the given stop token has been requested to end execution.
- typedef Lambda(void, const CnxStopToken*) CnxJThreadLambda
- When spawning a new
CnxJThread, aLambda(void, const CnxStopToken*)is used as its startup routine. This typedef allows for receiving that startup routine as a function parameter. - CnxResult(CnxJThread)
- Spawns a new
CnxJThread, with the givenCnxJThreadLambdaas its startup routine. - CnxResult cnx_jthread_init(CnxJThread*restrict thread, CnxJThreadLambda lambda)
- Spawns a new
CnxJThread, with the givenCnxJThreadLambdaas its startup routine. - CnxResult cnx_jthread_join(CnxJThread*restrict thread)
- Joins the given
CnxJThread, blocking until its execution has completed. - void cnx_jthread_free(void* thread)
- Frees the given
CnxJThread, blocking until it's joined or joining fails. - CnxResult(CnxTLSKey) cnx_tls_new(void *data
- Creates a new thread-local storage.
- CnxResult cnx_tls_init(CnxTLSKey*restrict key, void* data, void(__CNX_TLS_DESTRUCTOR_TAG*destructor)(void*))
- Initializes a thread-local storage and associates it with the key pointed to by
key - void* cnx_tls_get(CnxTLSKey key)
- Retrieves the current value of the thread-local storage associated with
key - CnxResult cnx_tls_set(CnxTLSKey key, void* data)
- Sets the value of the thread-local storage associated with
keytodata
Defines
- #define thread_local
- A variable declared as
thread_localis local to the current thread and guaranteed to not be accessible by other threads. - #define cnx_jthread_is_null(thread)
- Checks if the given thread handle is null (if it has been initialized)
- #define cnx_jthread_get_id(thread)
- Gets the ID of the current thread.
- #define cnx_jthread_detach(thread)
- Separates execution of the thread associated with the
CnxJThreadthread handle from the handle.
Typedef documentation
typedef __cnx_basic_mutex CnxBasicMutex
#include <include/Cnx/Thread.h>
CnxBasicMutex is the basic mutual exclusion object type provided by Cnx's threading and synchronization API. Using a CnxBasicMutex to control access to shared resources will ensure that all access is synchronized and mutually exclusive between threads.
typedef __cnx_recursive_basic_mutex CnxRecursiveBasicMutex
#include <include/Cnx/Thread.h>
CnxRecursiveBasicMutex is the basic reentrant mutual exclusion object type provided by Cnx's threading and synchronization API. Using a CnxRecursiveBasicMutex to control access to shared resources will ensure that all access is synchronized and mutually exclusive between threads, and allows for rentrant ownership of the lock on that access.
typedef __cnx_condvar CnxBasicCondvar
#include <include/Cnx/Thread.h>
CnxBasicCondvar is the Condition Variable object type provided by Cnx's threading and synchronization API. Using a CnxBasicCondvar allows to block one or more threads until an event is triggered, without wasting CPU resources.
typedef __cnx_thread_id CnxThreadID
#include <include/Cnx/Thread.h>
A CnxThreadID uniquely identifies an indiviual thread.
typedef __cnx_thread CnxThread
#include <include/Cnx/Thread.h>
A CnxThread is the handle type for basic OS-level threads provided by Cnx's threading and synchronization API. CnxThread provides the facilities for creating multiple threads and ending their execution, enabling concurrent tasks and operations to be performed.
typedef atomic_bool CnxStopToken
#include <include/Cnx/Thread.h>
A CnxStopToken is associated with a CnxJThread and is used to signal to it when it should end its execution.
typedef __cnx_tls_key CnxTLSKey
#include <include/Cnx/Thread.h>
A CnxTLSKey is the key type for creating, accessing, and modifying a thread-local storage object.
typedef __cnx_exec_once_flag CnxOnceFlag
#include <include/Cnx/Thread.h>
A CnxOnceFlag is a synchronization flag type for use with cnx_execute_once to ensure a given function is executed exactly once, regardless of how many threads attempt to call it, as long as all threads do so through the same CnxOnceFlag and cnx_execute_once
Function documentation
CnxResult(CnxBasicMutex)
#include <include/Cnx/Thread.h>
Creates a new mutex.
| Returns | A CnxBasicMutex if successful |
|---|
Creating a mutex can fail, depending on memory and operating system level constraints. If creating the mutex is successful, returns a CnxBasicMutex, otherwise returns an error.
CnxResult cnx_basic_mutex_init(CnxBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Initializes the mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to initalize |
| Returns | Ok if successful |
Initializing a mutex can fail, depending on memory and operating system level constraints. If initializing the mutex is successful, returns Ok, otherwise returns an error.
CnxResult cnx_basic_mutex_lock(CnxBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Unconditionally locks the mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to lock |
| Returns | Ok if successful |
Locking a mutex can fail (for example, if it's already locked on the calling thread). If locking the mutex is successful, returns Ok, otherwise returns an error.
bool cnx_basic_mutex_try_lock(CnxBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Attempts to lock the mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to lock |
| Returns | true if successful |
If locking the mutex is successful, return true.
CnxResult cnx_basic_mutex_unlock(CnxBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Unlocks the mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to unlock |
| Returns | Ok if successful |
Unlocking a mutex can fail (for example, if it's already unlocked). If unlocking the mutex is successful, returns Ok, otherwise returns an error.
CnxResult cnx_basic_mutex_free(CnxBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Destroys the mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to free |
| Returns | Ok if successful |
Destroying a mutex can fail (for example, it it's still in use by other threads). If destroying the mutex is successful, returns Ok, otherwise returns an error.
CnxResult(CnxRecursiveBasicMutex)
#include <include/Cnx/Thread.h>
Creates a new recursive mutex.
| Returns | A CnxRecursiveBasicMutex if successful |
|---|
Creating a mutex can fail, depending on memory and operating system level constraints. If creating the recursive mutex is successful, returns a CnxRecursiveBasicMutex, otherwise returns an error.
CnxResult cnx_recursive_basic_mutex_init(CnxRecursiveBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Initializes the recursive mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to initialize |
| Returns | Ok if successful |
Initializing a mutex can fail, depending on memory and operating system level constraints. If initializing the mutex is successful, returns Ok, otherwise returns an error.
CnxResult cnx_recursive_basic_mutex_lock(CnxRecursiveBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Unconditionally locks the recursive mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to lock |
| Returns | Ok if successful |
Locking a mutex can fail. If locking the recursive mutex is successful, returns Ok, otherwise returns an error.
bool cnx_recursive_basic_mutex_try_lock(CnxRecursiveBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Attempts to lock the recursive mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to lock |
| Returns | true if successful |
If locking the recursive mutex is successful, return true.
CnxResult cnx_recursive_basic_mutex_unlock(CnxRecursiveBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Unlocks the recursive mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to unlock |
| Returns | Ok if successful |
Unlocking a mutex can fail (for example, if it's already unlocked). If unlocking the recursive mutex is successful, returns Ok, otherwise returns an error.
CnxResult cnx_recursive_basic_mutex_free(CnxRecursiveBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Destroys the recursive mutex pointed to by mutex
| Parameters | |
|---|---|
| mutex | - The mutex to free |
| Returns | Ok if successful |
Destroying a mutex can fail (for example, it it's still in use by other threads). If destroying the recursive mutex is successful, returns Ok, otherwise returns an error.
CnxResult(CnxBasicCondvar)
#include <include/Cnx/Thread.h>
Creates a new condition variable, returning the result in a CnxResult
| Returns | A CnxRecursiveBasicMutex if successful |
|---|
Creating a condition variable can fail, depending on memory and operating system level constraints. If creating the condition variable is successful, returns a CnxBasicCondvar, otherwise returns an error
CnxResult cnx_basic_condvar_init(CnxBasicCondvar*restrict condvar)
#include <include/Cnx/Thread.h>
Initializes the condition variable pointed to by condvar
| Parameters | |
|---|---|
| condvar | - The condvar to initialize |
| Returns | Ok if successful |
Initializing a condition variable can fail, depending on memory and operating system level constraints. If initializing the condition variable is successful, returns Ok, otherwise returns an error
CnxResult cnx_basic_condvar_signal(CnxBasicCondvar*restrict condvar)
#include <include/Cnx/Thread.h>
Signals to the first thread waiting on the condition variable pointed to by condvar to wake and continue execution.
| Parameters | |
|---|---|
| condvar | - The condvar to signal on |
| Returns | Ok if successful |
Signalling with a condition variable can fail. If signalling with the condition variable is successful, returns Ok, otherwise returns an error.
CnxResult cnx_basic_condvar_broadcast(CnxBasicCondvar*restrict condvar)
#include <include/Cnx/Thread.h>
Signals to every thread waiting on the condition variable pointed to by condvar to wake and continue execution.
| Parameters | |
|---|---|
| condvar | - The condvar to broadcast on |
| Returns | Ok if successful |
Signalling with a condition variable can fail. If signalling with the condition variable is successful, returns Ok, otherwise returns an error.
CnxResult cnx_basic_condvar_wait(CnxBasicCondvar*restrict condvar,
CnxBasicMutex*restrict mutex)
#include <include/Cnx/Thread.h>
Blocks on the condition variable pointed to by condvar until the thread is signalled by it.
| Parameters | |
|---|---|
| condvar | - The condvar to wait on |
| mutex | - The mutex associated with the condvar |
| Returns | Ok if successful |
Unlocks the mutex pointed to by mutex and blocks on the condition variable pointed to by condvar until the thread is signalled by it. The mutex is re-locked again before the function returns. The mutex must be locked by the calling thread prior to calling this.
Waiting on a condition variable can fail. If waiting on the condition variable is successful, returns Ok, otherwise returns an error.
CnxResult cnx_basic_condvar_wait_for(CnxBasicCondvar*restrict condvar,
CnxBasicMutex*restrict mutex,
CnxDuration to_wait) cnx_disable_if(!mutex
#include <include/Cnx/Thread.h>
Blocks on the condition variable pointed to by condvar until the thread is signalled by it, or to_wait time has elapsed.
| Parameters | |
|---|---|
| condvar | - The condvar to wait on |
| mutex | - The mutex associated with the condvar |
| to_wait | - The amount of time to wait on the condvar |
| Returns | Ok if successful |
Unlocks the mutex pointed to by mutex and blocks on the condition variable pointed to by condvar until the thread is signalled by it, or to_wait time has elapsed. The mutex is re-locked again before the function returns. The mutex must be locked by the calling thread prior to calling this.
Waiting on a condition variable can fail. Returns Ok if a signal is received from the condition variable before to_wait has elapsed, otherwise returns an error.
CnxResult cnx_basic_condvar_wait_until(CnxBasicCondvar*restrict condvar,
CnxBasicMutex*restrict mutex,
CnxTimePoint stop_point) cnx_disable_if(!mutex
#include <include/Cnx/Thread.h>
Blocks on the condition variable pointed to by condvar until the thread is signalled by it, or the point in time indicated by stop_point time has been reached.
| Parameters | |
|---|---|
| condvar | - The condvar to wait on |
| mutex | - The mutex associated with the condvar |
| stop_point | - The point in time to stop waiting on the condvar |
| Returns | Ok if successful |
Unlocks the mutex pointed to by mutex and blocks on the condition variable pointed to by condvar until the thread is signalled by it, or the time indicated by stop_point has been reached. The mutex is re-locked again before the function returns. The mutex must be locked by the calling thread prior to calling this.
Waiting on a condition variable can fail. Returns Ok if a signal is received from the condition variable before to_wait has elapsed, otherwise returns an error.
CnxResult cnx_basic_condvar_free(CnxBasicCondvar*restrict condvar)
#include <include/Cnx/Thread.h>
Destroys the condition variable pointed to by condvar
| Parameters | |
|---|---|
| condvar | - The condvar to free |
| Returns | Ok if successful |
Destroying a condition variable can fail (for example, if its still in use by another thread). If destroying the condition variable is successful, returns Ok, otherwise, returns an error.
CnxResult cnx_execute_once(CnxOnceFlag*restrict flag,
void(*)(void) function) cnx_disable_if(!flag
#include <include/Cnx/Thread.h>
Executes the given function exactly once.
| Parameters | |
|---|---|
| flag | - The execute once flag associated with function's execution |
| function | - The function to execute exactly once |
| Returns | Ok if successful |
Executes the given function exactly once, regardless how many threads attempt to execute it, or if they attempt to execute it multiple times, as long as all attempts to call it go through cnx_execute_once using the same CnxOnceFlag
Executing the function can fail (for example, on Windows). If execution is successful, return Ok, otherwise returns an error.
CnxCompare cnx_thread_id_compare(CnxThreadID lhs,
CnxThreadID rhs)
#include <include/Cnx/Thread.h>
Compares the two CnxThreadIDs.
| Parameters | |
|---|---|
| lhs | - The id to compare |
| rhs | - The id to compare lhs to |
| Returns | A CnxCompare indicating how lhs compares to rhs |
bool cnx_thread_id_equal(CnxThreadID lhs,
CnxThreadID rhs)
#include <include/Cnx/Thread.h>
Returns whether the two CnxThreadIDs are equal.
| Parameters | |
|---|---|
| lhs | - The id to compare |
| rhs | - The id to compare lhs to |
| Returns | whether the two IDs are equal |
bool cnx_thread_id_less_than(CnxThreadID lhs,
CnxThreadID rhs)
#include <include/Cnx/Thread.h>
Returns whether the first CnxThreadID is less than the second.
| Parameters | |
|---|---|
| lhs | - The id to compare |
| rhs | - The id to compare lhs to |
| Returns | whether lhs is less than rhs |
bool cnx_thread_id_less_than_or_equal(CnxThreadID lhs,
CnxThreadID rhs)
#include <include/Cnx/Thread.h>
Returns whether the first CnxThreadID is less than or equal to the second.
| Parameters | |
|---|---|
| lhs | - The id to compare |
| rhs | - The id to compare lhs to |
| Returns | whether lhs is less than or equal to rhs |
bool cnx_thread_id_greater_than(CnxThreadID lhs,
CnxThreadID rhs)
#include <include/Cnx/Thread.h>
Returns whether the first CnxThreadID is greater than the second.
| Parameters | |
|---|---|
| lhs | - The id to compare |
| rhs | - The id to compare lhs to |
| Returns | whether lhs is greater than rhs |
bool cnx_thread_id_greater_than_or_equal(CnxThreadID lhs,
CnxThreadID rhs)
#include <include/Cnx/Thread.h>
Returns whether the first CnxThreadID is greater than or equal to the second.
| Parameters | |
|---|---|
| lhs | - The id to compare |
| rhs | - The id to compare lhs to |
| Returns | whether lhs is greater than or equal to rhs |
typedef Lambda(void) CnxThreadLambda
#include <include/Cnx/Thread.h>
When spawning a new thread, a Lambda(void) is used as its startup routine. This typedef allows for receiving that startup routine as a function parameter.
CnxResult(CnxThread)
#include <include/Cnx/Thread.h>
Spawns a new thread, with the given CnxThreadLambda as its startup routine.
| Returns | A CnxThread on success |
|---|
Spawns a new thread, with the given CnxThreadLambda as its startup routine. The given lambda will be automatically freed after the thread's execution completes.
Spawning a thread can fail due to memory or operating system level constraints. If spawning the thread is successful, returns a handle to the spawned thread. Otherwise, returns an error.
CnxResult cnx_thread_init(CnxThread*restrict thread,
CnxThreadLambda lambda)
#include <include/Cnx/Thread.h>
Spawns a new thread, with the given CnxThreadLambda as its startup routine.
| Parameters | |
|---|---|
| thread | - The pointer to thread handle to set as the handle to the spawned thread |
| lambda | - The lambda to invoke as the spawned thread's startup routine |
| Returns | Ok on success |
Spawns a new thread, with the given CnxThreadLambda as its startup routine. The given lambda will be automatically freed after the thread's execution completes.
Spawning a thread can fail due to memory or operating system level constraints. If spawning the thread is successful, the CnxThread pointed to by thread will be initialized with the handle to the spawned thread, and Ok will be returned. Otherwise, returns an error.
bool cnx_thread_is_null(const CnxThread*restrict thread)
#include <include/Cnx/Thread.h>
Checks if the given thread handle is null (if it has been initialized)
| Parameters | |
|---|---|
| thread | - The thread to check if is null |
| Returns | whether the thread is null |
CnxThreadID cnx_thread_get_id(const CnxThread*restrict thread)
#include <include/Cnx/Thread.h>
Gets the ID of the current thread.
| Parameters | |
|---|---|
| thread | - The thread to get the ID of |
| Returns | The ID of the given thread |
CnxResult cnx_thread_join(CnxThread*restrict thread)
#include <include/Cnx/Thread.h>
Joins the given thread, blocking until its execution has completed.
| Parameters | |
|---|---|
| thread | - The thread to join |
| Returns | Ok if successful |
Joining a thread can fail. Returns Ok if joining the thread is successful. Otherwise, returns an error.
CnxResult cnx_thread_detach(CnxThread*restrict thread)
#include <include/Cnx/Thread.h>
Separates execution of the thread associated with the given thread handle from the handle.
| Parameters | |
|---|---|
| thread | - The thread to detach |
| Returns | Ok if successful |
Separates execution of the thread associated with the given handle from that handle. When successfully detached, the associated thread will continue execution independently and will no longer be associated with any handle.
Detaching a thread can fail. Returns Ok if detaching the thread is successful. Otherwise, returns an error.
void cnx_thread_free(void* thread)
#include <include/Cnx/Thread.h>
Frees the given thread, blocking until it's joined or joining fails.
| Parameters | |
|---|---|
| thread | - The thread to free |
void cnx_this_thread_yield(void)
#include <include/Cnx/Thread.h>
Yields execution of the current thread, allowing the operating system to execute other threads until it decides to return execution to this one.
void cnx_this_thread_sleep_for(CnxDuration duration)
#include <include/Cnx/Thread.h>
Yields execution of the current thread until at least the given duration of time has passed.
| Parameters | |
|---|---|
| duration | - The minimum amount of time to yield execution for |
CnxThreadID cnx_this_thread_get_id(void)
#include <include/Cnx/Thread.h>
Returns the ID of the current thread.
| Returns | The ID of the current thread |
|---|
void cnx_stop_token_request_stop(CnxStopToken*restrict token)
#include <include/Cnx/Thread.h>
Requests the thread associated with the given stop token to end execution.
| Parameters | |
|---|---|
| token | - The token associated with the thread to end |
bool cnx_stop_token_stop_requested(const CnxStopToken*restrict token)
#include <include/Cnx/Thread.h>
Returns whether the thread associated with the given stop token has been requested to end execution.
| Parameters | |
|---|---|
| token | - The token associated with the thread to end |
| Returns | whether the thread has been requested to end |
typedef Lambda(void,
const CnxStopToken*) CnxJThreadLambda
#include <include/Cnx/Thread.h>
When spawning a new CnxJThread, a Lambda(void, const CnxStopToken*) is used as its startup routine. This typedef allows for receiving that startup routine as a function parameter.
CnxResult(CnxJThread)
#include <include/Cnx/Thread.h>
Spawns a new CnxJThread, with the given CnxJThreadLambda as its startup routine.
| Returns | A CnxJThread on success |
|---|
Spawns a new thread, with the given CnxJThreadLambda as its startup routine. The given lambda will be automatically freed after the thread's execution completes.
Spawning a thread can fail due to memory or operating system level constraints. If spawning the thread is successful, returns a handle to the spawned thread. Otherwise, returns an error.
CnxResult cnx_jthread_init(CnxJThread*restrict thread,
CnxJThreadLambda lambda)
#include <include/Cnx/Thread.h>
Spawns a new CnxJThread, with the given CnxJThreadLambda as its startup routine.
| Parameters | |
|---|---|
| thread | - The pointer to thread handle to set as the handle to the spawned thread |
| lambda | - The lambda to invoke as the spawned thread's startup routine |
| Returns | Ok on success |
Spawns a new thread, with the given CnxJThreadLambda as its startup routine. The given lambda will be automatically freed after the thread's execution completes.
Spawning a thread can fail due to memory or operating system level constraints. If spawning the thread is successful, the CnxThread pointed to by thread will be initialized with the handle to the spawned thread, and Ok will be returned. Otherwise, returns an error.
CnxResult cnx_jthread_join(CnxJThread*restrict thread)
#include <include/Cnx/Thread.h>
Joins the given CnxJThread, blocking until its execution has completed.
| Parameters | |
|---|---|
| thread | - The thread to join |
| Returns | Ok if successful |
Joining a thread can fail. Returns Ok if joining the thread is successful. Otherwise, returns an error.
void cnx_jthread_free(void* thread)
#include <include/Cnx/Thread.h>
Frees the given CnxJThread, blocking until it's joined or joining fails.
| Parameters | |
|---|---|
| thread | - The thread to free |
CnxResult(CnxTLSKey) cnx_tls_new(void *data
#include <include/Cnx/Thread.h>
Creates a new thread-local storage.
| Returns | A CnxTLSKey on success |
|---|
Creates a new thread-local storage that will be destroyed by the given destructor function at thread exit.
Creating a thread-local storage can fail. If creation is successful, the storage will be set to data and the CnxTLSKey associated with the storage will be returned. Otherwise, an error will be returned.
CnxResult cnx_tls_init(CnxTLSKey*restrict key,
void* data,
void(__CNX_TLS_DESTRUCTOR_TAG*destructor)(void*))
#include <include/Cnx/Thread.h>
Initializes a thread-local storage and associates it with the key pointed to by key
| Parameters | |
|---|---|
| key | |
| data | - The value to initialize the TLS to |
| Returns | A CnxTLSKey on success |
Initializes a new thread-local storage that will be destroyed by the given destructor function at thread exit, and associates the thread-local storage with the key pointed to by key.
Creating a thread-local storage can fail. If creation is successful, the storage will be set to data and the CnxTLSKey associated with the storage will be returned. Otherwise, an error will be returned.
void* cnx_tls_get(CnxTLSKey key)
#include <include/Cnx/Thread.h>
Retrieves the current value of the thread-local storage associated with key
| Parameters | |
|---|---|
| key | - The thread-local storage key to get the currently associated value of |
| Returns | The current value of the TLS, or nullptr |
If key is a key to a valid TLS, returns the current value of the TLS, otherwise returns a nullptr
CnxResult cnx_tls_set(CnxTLSKey key,
void* data)
#include <include/Cnx/Thread.h>
Sets the value of the thread-local storage associated with key to data
| Parameters | |
|---|---|
| key | - The thread-local storage key to set the associated value of |
| data | - The value to set the TLS to |
| Returns | Ok on successful |
Setting the value of a thread-local storage can fail. If setting the thread-local storage is successful, returns Ok. Otherwise, an error is returned
Define documentation
#define thread_local
#include <include/Cnx/Thread.h>
A variable declared as thread_local is local to the current thread and guaranteed to not be accessible by other threads.
#define cnx_jthread_is_null(thread)
#include <include/Cnx/Thread.h>
Checks if the given thread handle is null (if it has been initialized)
| Parameters | |
|---|---|
| thread | - The thread to check if is null |
| Returns | whether the thread is null |
#define cnx_jthread_get_id(thread)
#include <include/Cnx/Thread.h>
Gets the ID of the current thread.
| Parameters | |
|---|---|
| thread | - The thread to get the ID of |
| Returns | The ID of the given thread |
#define cnx_jthread_detach(thread)
#include <include/Cnx/Thread.h>
Separates execution of the thread associated with the CnxJThread thread handle from the handle.
| Parameters | |
|---|---|
| thread | - The thread to detach |
| Returns | Ok if successful |
Separates execution of the thread associated with the given handle from that handle. When successfully detached, the associated thread will continue execution independently and will no longer be associated with any handle.
Detaching a thread can fail. Returns Ok if detaching the thread is successful. Otherwise, returns an error.