module
CnxSharedLockCnxSharedLock
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
CnxSharedLock
provides 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 theCnxSharedLock
exits scope.
Typedefs
- using CnxSharedLock = struct CnxSharedLock
CnxSharedLock
provides 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 theCnxSharedLock
exits 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
CnxSharedMutexInterface
Trait object corresponding with the mutex associated with the givenCnxSharedLock
- bool cnx_shared_lock_owns_lock(CnxSharedLock*restrict lock)
- Returns whether the given
CnxSharedLock
currently 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
CnxSharedLock
as aSharedLock
ensures that it will be destroyed when it exits scope, releasing the lock on its associated mutex. - #define cnx_shared_lock(...)
- Creates a new
CnxSharedLock
associated 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 CnxSharedLock
without 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 CnxSharedLock
does 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 CnxSharedLock
will 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.