The lock() method of Synchronized<T> offers a LockedPtr<T> that can be used to access the data while holding the lock if the mutex type being used with Synchronized is a basic exclusive mutex type (as opposed to a shared mutex).
For as long as it is active, the lock is held by the LockedPtr object that lock() returns. To ensure that the LockedPtr is removed as soon as the lock is no longer required, it is preferable to declare a separate inner scope wherever possible.
wlock() and rlock()
Synchronized<T> offers a wlock() method that acquires an exclusive lock and a rlock() method that acquires a shared lock if the mutex type being used with Synchronized is a shared mutex type.
To prevent modification while just holding a shared lock, the LockedPtr provided by rlock() only grants constant access to the internal data.
As an alternative to the lock() API, Synchronized also
provides a withLock() method that executes a function or lambda
expression while holding the lock. The function receives a reference to the
data as its only argument.
This has a few benefits compared to lock():
• The lambda expression requires its own nested scope, making critical sections more visible in the code. When calling lock(), callers are advised to establish a new scope but are not required to do so. The withLock() function makes sure that a new scope is always defined.
• WithLock() encourages users to relinquish the lock as soon as feasible because a new scope is necessary. It is more difficult to unintentionally insert unnecessary code inside the vital section because the critical section scope is clearly visible in the code.
•Storing raw pointers or references to the protected data and utilising them beyond the critical part are made more challenging by the separate lambda scope.
ulock() and withULockPtr()
As long as the mutex type used to instantiate the Synchronized type has the same interface as the mutex types in the C++ standard library, or if LockTraits is specialised for the mutex type and the specialisation is apparent, Synchronized also enables upgrading and downgrading mutex lock levels.
unlock() and scopedUnlock()
Synchronized is a good mechanism for enforcing scoped
synchronization, but it has the inherent limitation that it requires the
critical section to be, well, scoped. Sometimes the code structure requires a
fleeting "escape" from the iron fist of synchronization, while still
inside the critical section scope.