Boost logo

Boost :

Subject: Re: [boost] [thread] Request review of new synchronisation object, boost::permit<>
From: Peter Dimov (lists_at_[hidden])
Date: 2014-05-06 13:01:30


Niall Douglas wrote:

> I still don't see how the compiler knows anything about that. The compiler
> can see a syscall, that is all.

It's the reverse. The compiler has to know that the syscall doesn't change
'result' in order to prove that 'result' is still zero. And the syscall in
this case does change 'result' - by executing a function that calls a lambda
that assigns to 'result'. So a compiler that "knew" that the syscall doesn't
change 'result' would be broken.

This is really not much different on a conceptual level from

int main()
{
    extern void f( int* );
    int result = 0;
    f( &result );
    std::cout << result << std::endl;
}

The compiler cannot know that f doesn't change 'result'.

> Your original point was that the docs should not claim no need for
> predicate testing during waits. I asserted this because unlike a condvar,
> permits carry state i.e. their own predicate, so predicate testing - where
> that predicate is for indicating a thread can continue - is unnecessary.

You assert that:

"You will never see spurious wakeups from a permit object -- [...]. This
means you don't need to do any wait predicate checking with permits..."

That is, you specifically claim that it is the absence of spurious wakeups
that frees one from predicate testing after wait returns, not the fact that
the permit has state of its own.

And the example I provided demonstrates a situation in which a thread sees
something that is indistinguishable from a spurious wakeup, from that
thread's point of view. The wait call returns, but the state of the program
is as if nobody has called notify_one.

The predicate P in my example represents program state. Your threads are
calling wait because they are waiting for something to occur. P=1 represents
a state in which this something has occurred. P=0 represents a state in
which it has not.

I can rephrase the example with a queue Q, so that P is Q.empty(), producers
push items onto Q, and consumers pop all the items and do something with
them. In this formulation, a spurious wakeup would mean that a consumer
returns from wait() and finds the queue empty, which is exactly what happens
in my example.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk