I have a std::condition_variable_any
that waits on a custom lock which is a composition of two mutexes (one std::mutex
and one shared-locked std::shared_mutex
). Its unlock()
operation simply unlocks both mutexes sequentially.
For example (pseudocode):
mutex mutex1;
shared_mutex mutex2;
condition_variable_any cv;
// acquiring the locks
DualLock lock(unique_lock(mutex1), shared_lock(mutex2));
// waiting
cv.wait(lock);
cv.wait()
should atomically unlock both mutex1
and mutex2
, and put the thread to sleep until cv
gets notified.
It it still guaranteed that the thread is sleeping and listening to the condition variable notification, once any of mutex1
or mutex2
is unlocked?
Or is it possible that one mutex gets unlocked, and a second thread locks it, sends the notification, but this first thread was not yet sleeping and listening. So the notification never arrived and no wakeup occurs.
If
DualLock
meets the requirements ofBasicLockable
, then the code will perform as hoped. If not, it won't.BasicLockable reference is here
This can never happen when condition variables are used properly. The wakeup of a condition variable cannot be interpreted as a signal of an event, since the documentation of condition_variable explains that there can be spurious wakeups.
At best, the notification is an indication that now may be a good time to test the condition you're waiting for (and you may do so in the secure knowledge that the test is protected by the mutex).
The state of the condition and the state of the blocked-ness of the current thread are two separate concerns.
Here's a better example (assumes that DualLock models BasicLockable correctly):
Your notifier would notify this way: