Subject: Re: [boost] [thread] Request review of new synchronisation object, boost::permit<>
From: Peter Dimov (lists_at_[hidden])
Date: 2014-05-05 08:38:18
Niall Douglas wrote:
> On 4 May 2014 at 23:25, Peter Dimov wrote:
> > > A non-consuming permit looks quite like a Win32 event object yes,
> > > except it has stronger guarantees useful for many-waiter
> > > many-signaller situations.
> > What are these stronger guarantees?
> They are listed at the top of the documentation page,
OK, I took that hint and read it. :-)
> but in essence a manual reset Win32 event object state change doesn't make
> strong guarantees about what happens to waiters. A permit grant, if
> non-consuming, will block until all waiting threads at the point of grant
> have been released. I believe the Win32 SetEvent() doesn't
This doesn't make sense to me. How do you differentiate between waiting
threads being released or non-released? SetEvent doesn't block, but after
it's called, the waiting threads are no longer blocked and will resume their
execution at scheduler's judgment. What would it mean for SetEvent to block
until they are released? What does released mean?
As it stands, permits look very much like events to me - not just
semantically similar, but equivalent. The manual reset event has grant,
revoke, wait; grant unblocks all current and future waiters. The auto reset
event has notify_one and wait, and notify_one unblocks one current or future
waiter, except that two or more notify_one calls when there are no waiters
are equivalent to one. It seems to me that this is exactly how permits work;
or if there's a difference, I can't see it.
Incidentally, I think that both your examples of condition variables not
working are wrong. The first one is where you say that
"The problem here is that the notify can cause the permit object to be
destroyed before the notify has exited -- which if tried with condition
variables may produce memory corruption."
Condition variables, in fact, do support this. If a condition variable
implementation causes memory corruption in this scenario, then it's buggy.
The second one is where you say
"And the compiler's optimiser is permitted by the standard to believe that
result has not changed between its initialisation and the first test of its
value, so ..."
The compiler optimizer is not permitted by the standard to hold such
beliefs. There is a mutex acquisition between result = 0 and result != 0;
this is an acquire operation, and acquire operations may synchronize-with
release operations in different threads, which synchronize-with edge may
cause the load of 'result' to see a different value unless 'result' can be
proven to be local to this thread, which it cannot be because of the [&].
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk