
Yuval Ronen wrote:
Ok, while trying to understand this, I made a list of kernel calls in each scenario. Both scenarios contain two threads: Thread1 is waiting on a CV. Thread2 locks the mutex (as it should), changes the CV predicate, notifies the CV, and unlock the mutex, either before or after the notify. Lets see what Thread2 does:
Scenario #1 ----------- 1. calls mutex_lock (kernel)
mutex_lock only goes to the kernel if the mutex isn't free.
2. changes predicate 3. calls mutex_unlock (kernel)
Likewise, mutex_unlock only goes to the kernel if between the lock and the unlock another thread has tried to lock the mutex and has been blocked by the kernel.
4. calls cond_signal (kernel changes thread1 state from "blocked" to "ready"
Scenario #2 ----------- 1. calls mutex_lock (kernel)
No difference here.
2. changes predicate 3. calls cond_signal (kernel changes thread1 state from "blocked on cond" to "blocked on mutex" 4. calls mutex_unlock (kernel changes thread1 state from "blocked" to "ready"
Guaranteed kernel call since at least one thread, thread1, is blocked waiting for the mutex.
Another thing (in addition to the better chance of avoiding bugs, as I explained in previous post) is that I believe that Scenario #2 better serves the "fairness" ideal, as described by Anthony Williams in http://lists.boost.org/Archives/boost/2006/10/112609.php.
You are free to use scenario #2 if you like. I'm just saying that it isn't the only option. :-)