====== 2015-12-13 - condition variable and lock ======
some time ago i was asked to make a code review of a multi-threaded code part. i found a code block like this:
std::condition_variable cv;
std::mutex m;
// ...a lot of code here...
std::unique_lock lock(m);
cv.notify_one();
and commented it as a "no-no" -- why to notify, while still having mutex locked?! it's obvious other thread will do something like this:
std::unique_lock lock(m);
cv.wait(lock, someConditionCheck);
// ... now process
so it means we're waking up a thread, just so it can block on mutex, then we unlock and wake it up again, so that it can process. sounds like a waste, doesn't it?
well -- it appears it does not work that way. in fact [[https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_signal.txt|POSIX advises signaling under a lock]]. dunno what are implementation details here, but doing this:
m.lock();
// ...
cv.notify_one();
m.unlock();
performs better than this:
m.lock()
// ...
m.unlock();
cv.notify_one();
which was quite surprising for me.
in fact the gain for linux system was ~3-10% (depending on the particular run and the machine test were run on), while at my friend's windows platform difference was as high as 30% ({{:blog:2015:12:13:condition_variable_and_lock.cpp|reference implementation}})!
even though i still do not know why it is so, the good news is that naturally written [[wp>RAII]] code:
std::lock_guard lock(m);
// ...
cv.notify_one();
works as expected and is superior, when it comes to performance.