CnxUniqueLock module
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.
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
CnxUniqueLockprovides 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 theCnxUniqueLockexits scope.
Typedefs
- using CnxUniqueLock = struct CnxUniqueLock
CnxUniqueLockprovides 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 theCnxUniqueLockexits 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
CnxMutexInterfaceTrait object corresponding with the mutex associated with the givenCnxUniqueLock - bool cnx_unique_lock_owns_lock(CnxUniqueLock*restrict lock)
- Returns whether the given
CnxUniqueLockcurrently 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
CnxUniqueLockas aUniqueLockensures that it will be destroyed when it exits scope, releasing the lock on its associated mutex. - #define cnx_unique_lock(...)
- Creates a new
CnxUniqueLockassociated 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 CnxUniqueLockwithout 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 CnxUniqueLockdoes 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 CnxUniqueLockwill 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.