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 block.
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 [&].