In principle, the @ixSci answer is correct, but there are few details. I rummaged a bit in the question and would like to add.
1) But what if I do not need to transfer data, but only need to wake the waiting thread (if there is one) - can I in this case NOT use the mutex?
The direct answer to this question is yes . In the examples on the cppreference here and here - that's exactly what they do. There, in general, all notify_one()/notify_all() calls are NOT made under the mutex.
As for the “spurious wake up” - the POSIX standard directly says:
It is true if you need to use it. Spurious wakeups from the pthread_cond_timedwait () or pthread_cond_wait () functions may occur. Since the return from pthread_cond_timedwait () or pthread_cond_wait () has been re-evaluated.
Thus, indeed, the only correct way to use condition_variable involves the presence of conditions that determine whether something has changed in the process memory or not, and which should be rechecked after waking up the flow from cv.wait() .
To ensure the specified correctness, it is necessary and sufficient to observe the following rule: update data in the T1 stream and check-and-wait on the same data in the T2 stream - must be performed under the same critical section.
notify() can be performed both in the same critical section and outside it.
Moreover, the documentation for notify_one even states that holding a lock during a notify() call is pessimization in the sense that if the lock during this call were already released, then the thread waiting for wait() could capture a mutex and would not break the law. So in some cases one would even recommend removing the lock before calling notify() . However, I put on a benchmark and it turned out that on my virtual machine this trick somehow slows down the program for some reason. So you need to test.
PS: it is not possible to implement check-and-wait using atomic types. yes, atomic.load() and cv.wait() are atomic, but their sequence is not, and in this case it is required that the predicate is checked for atomicity and cv.wait() called in the sequence.
PPS: a separate interesting moment is connected with the very concept of “spurious wake-up”, what it is. "spurious wake-up" is a behavior explicitly defined by the POSIX standard, in linux it may be due to the fact that the blocking syscall must be interrupted if the process receives a signal. Here I found a rather interesting post on this topic.
2) what is the cost of m_CondVar.notify_one() ; ? Will it be a regular syscall?
On linux, this is a syscall to the futex subsystem, which is actually not cheap. In strace it looks like this:
futex(0x6063ac, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x6063a8, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1})
In the same benchmark, I tried to compare notify() with neighboring syskollah, I got that notify() costs about the same as the mutex lock.
3) maybe you know an easier way to notify (without sending a message or transmitting, it does not matter) one thread from another?
I decided to test and compare among themselves the following methods:
The result is a benchmark here .
Semaphores and a bunch of mutex + condvar work about equally fast (apparently inside they have one implementation through futex), fdevent is about 2 times slower, mq_queue is already much slower.
So, it turns out, yes - the fastest way to notify between threads is mutex + condvar.