CnxSharedLock module
CnxSharedLock provides scoped non-exclusive (shared) locking of any higher-level mutexes (eg CnxMutex, CnxSharedMutex, etc.) provided by Cnx. It allows for a simple, concise way to acquire the shared lock on a mutex and ensure that lock is released appropriately.
Example:
// MyThing.h #include <Cnx/sync/SharedMutex.h> static MyType my_very_important_thing; static CnxSharedMutex* 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/SharedLock.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(CnxSharedMutex, DEFAULT_ALLOCATOR); *my_thing_mutex = cnx_shared_mutex_new(); { // use a `CnxUniqueLock` to exclusively 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) { // lock `my_thing_mutex` exclusively so we can write to what it's protecting __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) { // lock `my_thing_mutex` non-exclusively (shared) so that we can read from what it's // protecting __attr(maybe_unused) SharedLock lock = cnx_shared_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); // multiple threads can all call `get_value_from_my_thing` without blocking eachother, because // `my_thing_mutex` is a shared mutex and `get_value_from_my_thing` uses a shared lock 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 CnxSharedLock
CnxSharedLockprovides scoped non-exclusive (shared) locking of higher-level mutexes (egCnxSharedMutex,CnxSharedTimedMutex) provided by Cnx. It allows for a simple, concise way to acquire the shared lock on a mutex and ensure that lock is released appropriately when theCnxSharedLockexits scope.
Typedefs
- using CnxSharedLock = struct CnxSharedLock
CnxSharedLockprovides scoped non-exclusive (shared) locking of higher-level mutexes (egCnxSharedMutex,CnxSharedTimedMutex) provided by Cnx. It allows for a simple, concise way to acquire the shared lock on a mutex and ensure that lock is released appropriately when theCnxSharedLockexits scope.
Functions
- void cnx_shared_lock_lock(CnxSharedLock*restrict lock)
- Acquires a shared lock on the mutex associated with the given
CnxSharedLock - bool cnx_shared_lock_try_lock(CnxSharedLock*restrict lock)
- Attempts to acquire a shared lock on the mutex associated with the given
CnxSharedLock - bool cnx_shared_lock_try_lock_for(CnxSharedLock*restrict lock, CnxDuration duration)
- Attempts to acquire a shared lock on the mutex associated with the given
CnxSharedLock - bool cnx_shared_lock_try_lock_until(CnxSharedLock*restrict lock, CnxTimePoint stop_point)
- Attempts to acquire a shared lock on the mutex associated with the given
CnxSharedLock - void cnx_shared_lock_unlock(CnxSharedLock*restrict lock)
- Unlocks the mutex associated with the given
CnxSharedLock - CnxSharedMutexInterface cnx_shared_lock_mutex(CnxSharedLock*restrict lock)
- Returns the
CnxSharedMutexInterfaceTrait object corresponding with the mutex associated with the givenCnxSharedLock - bool cnx_shared_lock_owns_lock(CnxSharedLock*restrict lock)
- Returns whether the given
CnxSharedLockcurrently owns a non-exclusive (shared) lock on its associated mutex. - void cnx_shared_lock_free(void* lock)
- Destroys the given
CnxSharedLock, unlocking its associated mutex if it owns a lock on it.
Defines
- #define SharedLock
- Declaring a
CnxSharedLockas aSharedLockensures that it will be destroyed when it exits scope, releasing the lock on its associated mutex. - #define cnx_shared_lock(...)
- Creates a new
CnxSharedLockassociated with the given mutex.
Typedef documentation
typedef struct CnxSharedLock CnxSharedLock
#include <include/Cnx/sync/SharedLock.h>
CnxSharedLock provides scoped non-exclusive (shared) locking of higher-level mutexes (eg CnxSharedMutex, CnxSharedTimedMutex) provided by Cnx. It allows for a simple, concise way to acquire the shared lock on a mutex and ensure that lock is released appropriately when the CnxSharedLock exits scope.
To ensure that a CnxSharedLock is appropriately destroyed when it leaves scope, releasing the lock on its associated mutex, declare it as a SharedLock.
A CnxSharedLock should never be copied, to do so is undefined behavior. A CnxSharedLock 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 SharedLock, or manually unlock the mutex before it returns.
Example:
// MyThing.h #include <Cnx/sync/SharedMutex.h> static MyType my_very_important_thing; static CnxSharedMutex* 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 <Cnx/sync/SharedLock.h> #include "MyThing.h" void init_my_thing(void) { if(my_thing_mutex == nullptr) { my_thing_mutex = cnx_allocator_allocate_t(CnxSharedMutex, DEFAULT_ALLOCATOR); *my_thing_mutex = cnx_shared_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(CnxSharedLock lock) { // move lock into lock2 so that the mutex will be unlocked at scope exit __attr(maybe_unused) SharedLock 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); SharedLock lock1 = cnx_shared_lock(*my_thing_mutex); my_val = get_value_from_my_thing(move(lock1)); // do something with my_val SharedLock lock2 = cnx_shared_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)); SharedLock lock = cnx_shared_lock(*my_thing_mutex); newval = get_value_from_my_thing(move(lock)); } my_val = newval; // do something with new value
Function documentation
void cnx_shared_lock_lock(CnxSharedLock*restrict lock)
#include <include/Cnx/sync/SharedLock.h>
Acquires a shared lock on the mutex associated with the given CnxSharedLock
| Parameters | |
|---|---|
| lock | - The CnxSharedLock associated with the mutex to lock non-exclusively |
bool cnx_shared_lock_try_lock(CnxSharedLock*restrict lock)
#include <include/Cnx/sync/SharedLock.h>
Attempts to acquire a shared lock on the mutex associated with the given CnxSharedLock
| Parameters | |
|---|---|
| lock | - The CnxSharedLock associated with the mutex to lock non-exclusively |
| Returns | whether locking the mutex was successful |
bool cnx_shared_lock_try_lock_for(CnxSharedLock*restrict lock,
CnxDuration duration)
#include <include/Cnx/sync/SharedLock.h>
Attempts to acquire a shared lock on the mutex associated with the given CnxSharedLock
| Parameters | |
|---|---|
| lock | - The CnxSharedLock 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 a shared 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_shared_lock_try_lock_until(CnxSharedLock*restrict lock,
CnxTimePoint stop_point)
#include <include/Cnx/sync/SharedLock.h>
Attempts to acquire a shared lock on the mutex associated with the given CnxSharedLock
| Parameters | |
|---|---|
| lock | - The CnxSharedLock 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 a shared 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_shared_lock_unlock(CnxSharedLock*restrict lock)
#include <include/Cnx/sync/SharedLock.h>
Unlocks the mutex associated with the given CnxSharedLock
| Parameters | |
|---|---|
| lock | - The CnxSharedLock associated with the mutex to unlock |
CnxSharedMutexInterface cnx_shared_lock_mutex(CnxSharedLock*restrict lock)
#include <include/Cnx/sync/SharedLock.h>
Returns the CnxSharedMutexInterface Trait object corresponding with the mutex associated with the given CnxSharedLock
| Parameters | |
|---|---|
| lock | - The CnxSharedLock to get the associated mutex of |
| Returns | the CnxSharedMutexInterface Trait object of the mutex associated with the given lock |
bool cnx_shared_lock_owns_lock(CnxSharedLock*restrict lock)
#include <include/Cnx/sync/SharedLock.h>
Returns whether the given CnxSharedLock currently owns a non-exclusive (shared) lock on its associated mutex.
| Parameters | |
|---|---|
| lock | - The CnxSharedLock to check if owns a shared lock on its associated mutex |
| Returns | whether lock owns a lock on its mutex |
void cnx_shared_lock_free(void* lock)
#include <include/Cnx/sync/SharedLock.h>
Destroys the given CnxSharedLock, unlocking its associated mutex if it owns a lock on it.
| Parameters | |
|---|---|
| lock | - The CnxSharedLock to destroy |
Define documentation
#define SharedLock
#include <include/Cnx/sync/SharedLock.h>
Declaring a CnxSharedLock as a SharedLock ensures that it will be destroyed when it exits scope, releasing the lock on its associated mutex.
#define cnx_shared_lock(...)
#include <include/Cnx/sync/SharedLock.h>
Creates a new CnxSharedLock associated with the given mutex.
| Parameters | |
|---|---|
| ... |
|
| Returns | a CnxSharedLock constructed with the specified behavior |
Creates a new CnxSharedLock associated with the given mutex. If an instance of a tag type is NOT given to specify construction behavior, this will block until the shared 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 CnxSharedLockwithout acquiring the lock on the given mutex. The mutex will need to be manually locked (via the shared lock) later - A
cnx_: The shared lock has already been acquired, so theadopt_ lock_ t CnxSharedLockdoes not need to acquire it. Behavior will otherwise proceed as if no tag type instance were given. - A
cnx_: Attempt to acquire the shared lock on the given mutex during construction. Thetry_ lock_ t CnxSharedLockwill need to be queried as to whether it successfully acquired the lock withcnx_shared_lock_owns_lock, but otherwise behavior will proceed as if no tag type instance were given.