CnxRecursiveMutex struct
#include <include/Cnx/sync/Mutex.h>
CnxRecursiveMutex
is a higher-level mutex type, directly comparable to C++'s std::recursive_mutex`, for use when an algorithm requires that a thread be able to lock the same mutex multiple times in its control flow. While such an algorithm would cause the thread to deadlock itself when used with a normal mutex, this is the intended task for a recursive mutex. For example, if a recursive algorithm requires synchronization using the same mutex at multiple levels of recursion, and one level of the algorithm can't release the lock before calling the next, a CnxRecursiveMutex
would make this type of algorithm possible and prevent the thread from deadlocking itself.
Example:
// MyThing.h #include <Cnx/sync/Mutex.h> static MyType my_very_important_thing; static CnxRecursiveMutex* 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 "MyThing.h" void init_my_thing(void) { if(my_thing_mutex == nullptr) { my_thing_mutex = cnx_allocator_allocate_t(CnxRecursiveMutex, DEFAULT_ALLOCATOR); *my_thing_mutex = cnx_recursive_mutex_new(); cnx_recursive_mutex_lock(my_thing_mutex); my_very_important_thing = { // important intialization }; cnx_recursive_mutex_unlock(my_thing_mutex); } } void update_my_thing(u64 value) { cnx_mutex_lock(my_thing_mutex); let adjusted_value = static_cast(u64)(4 * value); if(adjusted_value < 46) { // even though we've already acquired the lock on `my_thing_mutex`, and this will try to // acquire it again, that's OK because we're using a recursive mutex update_my_thing(adjusted_value); } else { my_very_important_thing.value = adjusted_value; } cnx_mutex_unlock(my_thing_mutex); } u64 get_value_from_my_thing(void) { cnx_mutex_lock(my_thing_mutex); let val = my_very_important_thing.value; cnx_mutex_unlock(my_thing_mutex); return val; } // 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