module
CnxUniqueLockCnxUniqueLock
provides scoped exclusive locking of any higher-level mutexes (eg CnxMutex
, CnxSharedMutex
, etc.) provided by Cnx. It allows for a simple, concise way to acquire the exclusive lock on a mutex and ensure that lock is released appropriately.
Example:
// MyThing.h #include <Cnx/sync/Mutex.h> static MyType my_very_important_thing; static CnxMutex* my_thing_mutex; void init_my_thing(void); void update_my_thing(u64 value); u64 get_value_from_my_thing(void); // MyThing.c #include <Cnx/Allocators.h> #include <Cnx/sync/UniqueLock.h> #include "MyThing.h" void init_my_thing(void) { if(my_thing_mutex == nullptr) { my_thing_mutex = cnx_allocator_allocate_t(CnxMutex, DEFAULT_ALLOCATOR); *my_thing_mutex = cnx_mutex_new(); { // use a `CnxUniqueLock` to lock `my_thing_mutex`. // mark `lock` as `maybe_unused` so we don't get warnings about an unused variable __attr(maybe_unused) UniqueLock lock = cnx_unique_lock(*my_thing_mutex); my_very_important_thing = { // important intialization }; // `lock` automatically destroyed at scope end, releasing the lock on `my_thing_mutex` } } } void update_my_thing(u64 value) { __attr(maybe_unused) UniqueLock lock = cnx_unique_lock(*my_thing_mutex); my_very_important_thing.value = value; // `lock` automatically destroyed at scope end, releasing the lock on `my_thing_mutex` } u64 get_value_from_my_thing(void) { __attr(maybe_unused) UniqueLock lock = cnx_unique_lock(*my_thing_mutex); let val = my_very_important_thing.value; return val; // `lock` automatically destroyed at scope end, releasing the lock on `my_thing_mutex` } // do some compute intensive task... // update the value update_my_thing(new_value); my_val = get_value_from_my_thing(); // do something with my_val let_mut newval = get_value_from_my_thing(); while(newval == my_val) { cnx_this_thread_sleep_for(cnx_milliseconds(100)); newval = get_value_from_my_thing(); } my_val = newval; // do something with new value
Classes
- struct CnxUniqueLock
CnxUniqueLock
provides scoped exclusive locking of any higher-level mutexes (egCnxMutex
,CnxSharedMutex
, etc.) provided by Cnx. It allows for a simple, concise way to acquire the exclusive lock on a mutex and ensure that lock is released appropriately when theCnxUniqueLock
exits scope.
Typedefs
- using CnxUniqueLock = struct CnxUniqueLock
CnxUniqueLock
provides scoped exclusive locking of any higher-level mutexes (egCnxMutex
,CnxSharedMutex
, etc.) provided by Cnx. It allows for a simple, concise way to acquire the exclusive lock on a mutex and ensure that lock is released appropriately when theCnxUniqueLock
exits scope.
Functions
- void cnx_unique_lock_lock(CnxUniqueLock*restrict lock)
- Acquires an exclusive lock on the mutex associated with the given
CnxUniqueLock
- bool cnx_unique_lock_try_lock(CnxUniqueLock*restrict lock)
- Attempts to acquire an exclusive lock on the mutex associated with the given
CnxUniqueLock
- bool cnx_unique_lock_try_lock_for(CnxUniqueLock*restrict lock, CnxDuration duration)
- Attempts to acquire an exclusive lock on the mutex associated with the given
CnxUniqueLock
- bool cnx_unique_lock_try_lock_until(CnxUniqueLock*restrict lock, CnxTimePoint stop_point)
- Attempts to acquire an exclusive lock on the mutex associated with the given
CnxUniqueLock
- void cnx_unique_lock_unlock(CnxUniqueLock*restrict lock)
- Unlocks the mutex associated with the given
CnxUniqueLock
- CnxMutexInterface cnx_unique_lock_mutex(CnxUniqueLock*restrict lock)
- Returns the
CnxMutexInterface
Trait object corresponding with the mutex associated with the givenCnxUniqueLock
- bool cnx_unique_lock_owns_lock(CnxUniqueLock*restrict lock)
- Returns whether the given
CnxUniqueLock
currently owns an exclusive lock on its associated mutex. - void cnx_unique_lock_free(void* lock)
- Destroys the given
CnxUniqueLock
, unlocking its associated mutex if it owns a lock on it.
Defines
- #define UniqueLock
- Declaring a
CnxUniqueLock
as aUniqueLock
ensures that it will be destroyed when it exits scope, releasing the lock on its associated mutex. - #define cnx_unique_lock(...)
- Creates a new
CnxUniqueLock
associated with the given mutex.
Typedef documentation
typedef struct CnxUniqueLock CnxUniqueLock
#include <include/Cnx/sync/UniqueLock.h>
CnxUniqueLock
provides scoped exclusive locking of any higher-level mutexes (eg CnxMutex
, CnxSharedMutex
, etc.) provided by Cnx. It allows for a simple, concise way to acquire the exclusive lock on a mutex and ensure that lock is released appropriately when the CnxUniqueLock
exits scope.
To ensure that a CnxUniqueLock
is appropriately destroyed when it leaves scope, releasing the lock on its associated mutex, declare it as a UniqueLock
.
A CnxUniqueLock
should never be copied, to do so is undefined behavior. A CnxUniqueLock
may be moved into a new scope with move
(eg. passing it to a function as a parameter), however. If this is done though, the receiving function will need to either move the parameter into a local variable declared as a UniqueLock
, or manually unlock the mutex before it returns.
Example:
// MyThing.h #include <Cnx/sync/Mutex.h> static MyType my_very_important_thing; static CnxMutex* my_thing_mutex; void init_my_thing(void); void update_my_thing(u64 value); u64 get_value_from_my_thing(void); // MyThing.c #include <Cnx/Allocators.h> #include <Cnx/sync/UniqueLock.h> #include "MyThing.h" void init_my_thing(void) { if(my_thing_mutex == nullptr) { my_thing_mutex = cnx_allocator_allocate_t(CnxMutex, DEFAULT_ALLOCATOR); *my_thing_mutex = cnx_mutex_new(); { // use a `CnxUniqueLock` to lock `my_thing_mutex`. // mark `lock` as `maybe_unused` so we don't get warnings about an unused variable __attr(maybe_unused) UniqueLock lock = cnx_unique_lock(*my_thing_mutex); my_very_important_thing = { // important intialization }; // `lock` automatically destroyed at scope end, releasing the lock on `my_thing_mutex` } } } void update_my_thing(u64 value) { __attr(maybe_unused) UniqueLock lock = cnx_unique_lock(*my_thing_mutex); my_very_important_thing.value = value; // `lock` automatically destroyed at scope end, releasing the lock on `my_thing_mutex` } u64 get_value_from_my_thing(CnxUniqueLock lock) { // move lock into lock2 so that the mutex will be unlocked at scope exit __attr(maybe_unused) UniqueLock lock2 = move(lock); let val = my_very_important_thing.value; return val; // `lock2` automatically destroyed at scope end, releasing the lock on `my_thing_mutex` } // do some compute intensive task... // update the value update_my_thing(new_value); UniqueLock lock1 = cnx_unique_lock(*my_thing_mutex); my_val = get_value_from_my_thing(move(lock1)); // do something with my_val UniqueLock lock2 = cnx_unique_lock(*my_thing_mutex); let_mut newval = get_value_from_my_thing(move(lock2)); while(newval == my_val) { cnx_this_thread_sleep_for(cnx_milliseconds(100)); UniqueLock lock = cnx_unique_lock(*my_thing_mutex); newval = get_value_from_my_thing(move(lock)); } my_val = newval; // do something with new value
Function documentation
void cnx_unique_lock_lock(CnxUniqueLock*restrict lock)
#include <include/Cnx/sync/UniqueLock.h>
Acquires an exclusive lock on the mutex associated with the given CnxUniqueLock
Parameters | |
---|---|
lock | - The CnxUniqueLock associated with the mutex to lock |
bool cnx_unique_lock_try_lock(CnxUniqueLock*restrict lock)
#include <include/Cnx/sync/UniqueLock.h>
Attempts to acquire an exclusive lock on the mutex associated with the given CnxUniqueLock
Parameters | |
---|---|
lock | - The CnxUniqueLock associated with the mutex to lock |
Returns | whether locking the mutex was successful |
bool cnx_unique_lock_try_lock_for(CnxUniqueLock*restrict lock,
CnxDuration duration)
#include <include/Cnx/sync/UniqueLock.h>
Attempts to acquire an exclusive lock on the mutex associated with the given CnxUniqueLock
Parameters | |
---|---|
lock | - The CnxUniqueLock associated with the mutex to lock |
duration | - The maximum amount of time to spend trying to acquire the lock, after which acquisition will timeout and fail |
Returns | whether locking the mutex was successful |
Attempts to acquire an exclusive lock on the mutex associated with lock
. If the amount of time specified by duration
has passed before successfully acquiring the lock, this will timeout and cease acquisition.
bool cnx_unique_lock_try_lock_until(CnxUniqueLock*restrict lock,
CnxTimePoint stop_point)
#include <include/Cnx/sync/UniqueLock.h>
Attempts to acquire an exclusive lock on the mutex associated with the given CnxUniqueLock
Parameters | |
---|---|
lock | - The CnxUniqueLock associated with the mutex to lock |
stop_point | - The point in time after which acquisition should timeout and fail, if the lock has not yet been acquired |
Returns | whether locking the mutex was successful |
Attempts to acquire an exclusive lock on the mutex associated with lock
. If the point in time specified by stop_point
has passed before successfully acquiring the lock, this will timeout and cease acquisition.
void cnx_unique_lock_unlock(CnxUniqueLock*restrict lock)
#include <include/Cnx/sync/UniqueLock.h>
Unlocks the mutex associated with the given CnxUniqueLock
Parameters | |
---|---|
lock | - The CnxUniqueLock associated with the mutex to unlock |
CnxMutexInterface cnx_unique_lock_mutex(CnxUniqueLock*restrict lock)
#include <include/Cnx/sync/UniqueLock.h>
Returns the CnxMutexInterface
Trait object corresponding with the mutex associated with the given CnxUniqueLock
Parameters | |
---|---|
lock | - The CnxUniqueLock to get the associated mutex of |
Returns | the CnxMutexInterface Trait object of the mutex associated with the given lock |
bool cnx_unique_lock_owns_lock(CnxUniqueLock*restrict lock)
#include <include/Cnx/sync/UniqueLock.h>
Returns whether the given CnxUniqueLock
currently owns an exclusive lock on its associated mutex.
Parameters | |
---|---|
lock | - The CnxUniqueLock to check if owns an exclusive lock on its mutex |
Returns | whether lock owns a lock on its mutex |
void cnx_unique_lock_free(void* lock)
#include <include/Cnx/sync/UniqueLock.h>
Destroys the given CnxUniqueLock
, unlocking its associated mutex if it owns a lock on it.
Parameters | |
---|---|
lock | - The CnxUniqueLock to destroy |
Define documentation
#define UniqueLock
#include <include/Cnx/sync/UniqueLock.h>
Declaring a CnxUniqueLock
as a UniqueLock
ensures that it will be destroyed when it exits scope, releasing the lock on its associated mutex.
#define cnx_unique_lock(...)
#include <include/Cnx/sync/UniqueLock.h>
Creates a new CnxUniqueLock
associated with the given mutex.
Parameters | |
---|---|
... |
|
Returns | a CnxUniqueLock constructed with the specified behavior |
Creates a new CnxUniqueLock
associated with the given mutex. If an instance of a tag type is NOT given to specify construction behavior, this will block until the exclusive lock is acquired on the given mutex. If an instance of a tag type specifying construction behavior IS given, however, then construction will behave according to the given tag type:
- A
cnx_
: Construct thedefer_ lock_ t CnxUniqueLock
without acquiring the lock on the given mutex. The mutex will need to be manually locked (via the unique lock) later - A
cnx_
: The lock has already been acquired, so theadopt_ lock_ t CnxUniqueLock
does not need to acquire it. Behavior will otherwise proceed as if no tag type instance were given. - A
cnx_
: Attempt to acquire the lock on the given mutex during construction. Thetry_ lock_ t CnxUniqueLock
will need to be queried as to whether it successfully acquired the lock withcnx_unique_lock_owns_lock
, but otherwise behavior will proceed as if no tag type instance were given.