boost threads: notify_one vs. notify_all

boost threads: notify_one vs. notify_all

Post by isaacjun » Sat, 17 Apr 2004 15:05:01


For a given condition variable, notify_one will wake up only one
blocking thread, while notify_all wakes up all blocking threads. My
question is why do both exist? In my mind, there shouldn't be
correctness issues, because the lock must automatically be reacquired
within the blocker's wait() function before the woken thread can
resume, correct? Is it simply efficiency, or are all woken threads
simply allowed to continue without having to fight for the lock on the
shared mutex?

Isaac

[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Alexander » Sun, 18 Apr 2004 15:10:43


>
> For a given condition variable, notify_one will wake up only one
> blocking thread, while notify_all wakes up all blocking threads. My
> question is why do both exist? In my mind, there shouldn't be
> correctness issues, because the lock must automatically be reacquired
> within the blocker's wait() function before the woken thread can
> resume, correct?

Correct.

> Is it simply efficiency,

Yep. "notify_one() { notify_all(); }" is totally correct (under
POSIX) but somewhat inefficient. ;-)

> or are all woken threads
> simply allowed to continue without having to fight for the lock on the
> shared mutex?

Nope. Not with POSIX condvars. http://www.yqcomputer.com/

regards,
alexander.

[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

 
 
 

boost threads: notify_one vs. notify_all

Post by Ben Hutchi » Mon, 19 Apr 2004 04:22:28


That is correct.


Just for efficiency. If it is known that all waiting threads are
waiting for exactly the same logical condition then it is safe and
more efficient to wake just one of them. Otherwise waking just one
may lead to deadlock.

[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Andreas Hu » Mon, 19 Apr 2004 07:27:11


mutex first thing after waking up. So, when you have two threads waiting on
a condition variable, notify_all() will lead to the following sequence:

1. Both threads are woken up
2. Thread A acquires the mutex. Thread B blocks on the mutex
3. Thread A releases the mutex. Thread B acquires the mutex

Regards,

Andreas


[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Andreas Hu » Mon, 19 Apr 2004 09:44:48


I understand the OPs question and your answer such that there is no semantic
difference between notfy_one() and notify_all(). I agree that for *some*
uses of condvars there really is no difference. Namely when the thread that
has won the battle for the mutex *never* releases it. However that is a
rather academic case, isn't it?
The thread that has successfully acquired the mutex will usually at some
later point release the mutex (if only to wait on the condvar again) what
allows another thread that is currently blocking on the mutex to acquire it.

In other words, notify_all() wakes *all* waiting threads. Sure, they can
then acquire and later release the mutex only one by one, but the fact
remains that they will eventually all go through the "critical section".
OTOH, notify_one() only wakes exactly one thread.

I can't speak for POSIX condvars but the implementation in
"thread/condition.hpp" seems to do it exactly this way, even for POSIX.

Regards,

Andreas


[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Alexander » Tue, 20 Apr 2004 18:58:08


[...]

Nope. "notify_one()" [aka signal()] can unblock multiple threads.
Spurious wakes are allowed under POSIX.

void signal() {
unsigned int wakeups;
{
mutex::guard guard(m_mutex);
if (0 != (wakeups = m_waiters[0] > m_wakeups)) {
if (EOC() == ++m_futex) {
wakeups = ALL;
m_wakeups = m_waiters[0];
}
else
++m_wakeups;
}
}
if (wakeups)
m_futex.wake(wakeups);
}

void broadcast() {
bool wakeups;
{
mutex::guard guard(m_mutex);
if (false != (wakeups = m_waiters[0] > m_wakeups)) {
++m_futex;
m_wakeups = m_waiters[0];
}
}
if (wakeups)
m_futex.wake(ALL);
}

http://www.yqcomputer.com/
http://www.yqcomputer.com/


Its windows impl's dtor is still broken. See pthreads-win32.


BTW, fire a search on "wait morphing".

regards,
alexander.

[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Michael Gl » Wed, 21 Apr 2004 03:53:37


[snip]


Could you be more specific? I assume you mean the destructor of the
condition class; in what way is it broken?


What part of it, and what would I be looking for? A comment about the
brokenness of the boost.thread condition class? A better
implementation?


Mike



[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Andreas Hu » Thu, 22 Apr 2004 04:24:43


True, boost::thread docs also mention spurious wakeups. So, notify_one()
wakes *at least* one thread, not exactly one.

Thanks for the clarification.

Regards,

Andreas


[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
 
 

boost threads: notify_one vs. notify_all

Post by Alexander » Thu, 22 Apr 2004 04:34:14


[...]

POSIX says that it's OK to destroy a condition variable once you've
signalled or broadcasted (or pthread_cancel()ed) to awaken the last
waiter(s). The basic idea is that with "wait-morphing", there's no
need for a waiter to touch the condition variable on awakening...
and that even without "wait-morphing", it's still better to do "the
right thing" on the implementation side, not application (barriers
differ*** in this respect, BTW). See example in "APPLICATION USAGE"
section at < http://www.yqcomputer.com/ ;.


You need to "close the gate" (lock the gate sema) in windows impl's
dtor. I suppose that you could find sort of "illustration" in
pthreads-win32 source (IIRC, both boost.thread and pthreads-win32
use the same underlying sema-based solution).

regards,
alexander.

***) (Both DRs were rejected. I was told that the standard is "clear
enough" as it is. ;-) )

http://www.yqcomputer.com/
http://www.yqcomputer.com/

[ See http://www.yqcomputer.com/ ]
[ comp.lang.c++.moderated. First time posters: Do this! ]