$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Roland Schwarz (roland.schwarz_at_[hidden])
Date: 2006-12-07 14:26:21
Yuval Ronen wrote:
> ... And it is only obvious that all reads and writes to the 
> shared-among-threads predicate should be locked. Shouldn't it?
Of course, the predicate access needs to be locked. But there is no
requirement for the signaling part, since this does not access the 
predicate.
> ... also greatly improve CV 
> performance on Windows).
Do you mean: Requirement to hold the lock while signaling will improve 
speed ?
If so I might tell you, that the intent of not requiring to hold the 
mutex while signaling is expected to improve speed. Butenhof 
(Programming with Posix Threads) says:
   "Although you must have the associated mutex locked to wait on a 
condition variable, you can signal (or broadcast) a condition variable 
with the associated mutex unlocked if that is more convenient. The 
advantage of doing so is that, on many systems, this may be more 
efficient. When a waiting thread awakens, it must first lock the mutex. 
If the thread awakens while a signaling thread holds the mutex, then the 
awakened thread must immediately block on the mutex - you've gone 
through two context switches to get back where you started. (There is an 
optimization, which I've called wait morphing, that moves a thread 
directly from the condition variable wait queue to the mutex wait queue 
in this case, without a context switch, when the mutex is locked. This 
optimization can produce a substantial performance benefit for many 
applications.)
Weighing on the other side is the fact that, if the mutex is not locked, 
any thread (not only the one being awakened) can lock the mutex prior to 
the thread being awakened. This race is one source of intercepted 
wakeups. A lower-priority thread, for example, might lock the mutex 
while another thread was about to awaken a very high-priority thread, 
delaying scheduling of the high-priority thread. If the mutex remains 
locked while signaling, this cannot happen - the high-priority waiter 
will be placed before the lower-priority waiter onr the mutex and will 
be scheduled first."
I might be wrong, but AFAIK "wait morphing" generally cannot be done in 
a user-space library, it needs to intimately interact with the scheduler.
> Providing an interface that will ensure for 
> notifying, locking the *same* mutex as when waiting, ...
...
> What I'm suggesting is that the condition constructor would accept a 
> mutex reference and store it. The Lock& argument to the wait() method 
> will be removed, as there's already a reference to the mutex. It might 
> also be useful to templatize the condition class for Mutex type:
What would this be of help for? Changing a predicate needs locking the 
mutex, not signaling it. If you mean that the signal function internally 
first should lock the mutex, signal and then unlock it, this would make 
things even worse (And is quite different from the case Butenhof 
addresses in the above citation, since this will be of no help in the 
priority case.)
Also putting the mutex into the condition ctor would make construction 
unnecessary complicated. E.g. how would you do in the following (quite 
common) case:
class foo {
mutex m;
condition c;
};
Btw.: I highly recommend reading Butenhofs book, it not only covers 
pthreads, but will help getting a better general understanding of 
threading too.
Regards,
Roland