Yesterday I wrote about How to synchronize data access, you should read it before continuing with this post, it will explain in detail the technique I will expand upon here. I’ll wait…

Alright! Now that you understand how a temporary RAII object can lock a mutex associated with an instance of an object, effectively synchronizing across multiple threads every method call, let’s talk about reader/writer locks.
R/W locks allow for two levels of synchronization: shared and exclusive. Shared lock allows multiple threads to simultaneously access an object under the assumption that said threads will perform only read operations (or to be more exact, operations which do not change the externally observable state of an object). Exclusive lock on the other hand can be held by only one thread at which point said thread is allowed to modify the object’s state and any data associated with it.

In order to implement this functionality I had to create two types of the locker object (the RAII holder of a mutex). Both lockers hold a reference to std::shared_mutex but one locker uses std::shared_lock while the other uses std::unique_lock to acquire ownership of the mutex. This approach is still transparent to the user with the following exception: a non-const instance of shared_synchronized<T> class must use std::as_const in order to acquire shared ownership ( const shared_synchronized<T>, shared_synchronized<const T>, and const shared_synchronized<const T> will always acquire shared lock; note that std::as_const performs a const_cast).


Implementation:
synchronized.hpp | synchronized.cpp


Leave a Reply