Since C++17(C++14) we have the std::shared_(timed_)mutex classes. Qt had an analogous class QReadWriteLock for a long time. QReadWriteLock's documentation says:
To ensure that writers aren't blocked forever by readers, readers attempting to obtain a lock will not succeed if there is a blocked writer waiting for access, even if the lock is currently only accessed by other readers. Also, if the lock is accessed by a writer and another writer comes in, that writer will have priority over any readers that might also be waiting.
As this is certainly a reasonable property, I wonder if std::shared_mutex and std::shared_timed_mutex behave in a similar way?
Official C++ Standard doesn't specify the std::shared_mutex
policy. Explanation could be found in original N2406 proposal
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#shared_mutex_imp) in shared_mutex Reference Implementation section:
A secondary motivation is to explain the lack of reader-writer priority policies in shared_mutex. This is due to an algorithm credited to Alexander Terekhov which lets the OS decide which thread is the next to get the lock without caring whether a unique lock or shared lock is being sought. This results in a complete lack of reader or writer starvation. It is simply fair.
Comparing to QReadWriteLock implementation (that is write-preferring):
To ensure that writers aren't blocked forever by readers, readers attempting to obtain a lock will not succeed if there is a blocked writer waiting for access, even if the lock is currently only accessed by other readers.
That's true for proposal's shared_mutex
as well, to make sure writer will not wait forever if new readers are continuing to come.
Also, if the lock is accessed by a writer and another writer comes in, that writer will have priority over any readers that might also be waiting.
That's NOT true for proposal's shared_mutex
, readers and writers have equal priorities in this case.
But unfortunately final C++ Standard document doesn't contain this reference implementation. Note that despite the fact GCC contains std::shared_mutex
implementation that is based on N2406 reference implementation, but on Linux it's not used by default, it uses pthread_rwlock_t
from POSIX threads lib (controlled by _GLIBCXX_USE_PTHREAD_RWLOCK_T
option in c++config.h
). pthread_rwlock_t
can be read-preferring or write-preferring depending on system setup and applied pthread
attributes. See related question for details: How to prevent writer starvation in a read write lock in pthreads
It isn't specified by the standard.
POSIX doesn't specify how pthread rwlocks must decide which lock request next succeeds, so it would be impossible to implement C++ std::shared_mutex
in terms of standard pthreads if it had such a requirement.
As this is certainly a reasonable property
It's certainly a reasonable property, but it's not the only reasonable property.
For example, GLIBC has a pthreads extension allowing you to choose from three rwlock policies: recursive prefer reader, recursive prefer writer and non-recursive prefer writer. Presumably recursive prefer writer isn't the correct choice for all programs.
To ensure that writers aren't blocked forever by readers ...
As an aside, this does nothing to ensure that writers aren't blocked forever by other writers.
The intuitively-perfectly-fair solution is shared-reader-preferred-exclusive-FIFO-ordered-writer, but this is unnecessarily heavyweight for many purposes.
The Qt version may be exactly perfect for Qt's use case, but it is only one point on the light/efficient -- heavy/fair spectrum.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With