Boost Users :
Subject: Re: [Boost-users] [thread] await hangs when using boost::promise/future
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2015-01-18 04:16:07
Le 18/01/15 07:14, Lee Clagett a écrit :
> On Sat, Jan 17, 2015 at 1:55 PM, Vicente J. Botet Escriba
> <vicente.botet_at_[hidden] <mailto:vicente.botet_at_[hidden]>> wrote:
> Le 17/01/15 16:36, Vicente J. Botet Escriba a écrit :
>> Le 17/01/15 15:36, Lee Clagett a écrit :
>> The continuation then tries to acquire the mutex (has_exception),
>> and blocks waiting for the set_value() to clear.
>> The continuation is executed in another thread and only when it
>> is ready (either there is a set_value or a set_exception). So the
>> continuation shouldn't block.
>>> set_value() is in turn waiting for the continuation thread to
>>> join because nothing else has a handle to the thread.
>> I don't understand how did you got this conclusion. Please could
>> you clarify? I can understand that the as the blocking is on the
>> shared future, the promise destructor will block in this case.
> This line here [
> ]. this_continuation_ptr is the last thing that references the
> continuation thread, so it tries to join it during destruction, while
> the mutex is held up the call stack. If the continuation thread calls
> a function on the future it receives, it then must wait for the same
> mutex which will never be released.
The mutex that is held is the mutex of the other future, not the one of
the continuation future. The fact that it joins is a consequence that
the user has not stored the future (as expects, but that with the
current interface I can not force).
>>> The best way to get around this is to _not_ ignore the returned
>>> future from the .then call. I also have patch that fixes the
>>> second bug, but fixing the first bug will require enough changes
>>> that will likely result in an obsolete patch.
>> Is the patch for Boost.Thread?
>> Thanks for your comments. I will try to fix this the blocking
>> issue asap but I suspect that this couldn't go into the next
>> Boost version :(
> I have a patch here [
> ] that addresses the deadlock issue, and should allow the code by the
> OP to work exactly as desired. However, the patch does not work as the
> docs indicate. Instead of blocking on the destructor of the
> continuation future, it will block in the destructor of the original
> future, OR the setter of the original promise (which could be its
> destructor in broken_promise case), whichever occurs last.
I will take a look, but I want to go towards the semantic of the
standard. The original future could be destructed before the
continuation future, and in fact this is usual the case.
> Fixing the .then() blocking issue is a little tricky because the
> destructor of the continuation future could need to wait for a thread
> that won't be launched until a value is set in the original promise.
I'm working on a fix (on a fix/blocking_future branch - the fix is not
yet visible). For the time been I have reached to fix async.
future::then() works also, but I have some yet unidentified issues with
> Is blocking in the destructor of the continuation future necessary? A
> callback signals when the original future has been set just the same.
> The negative is the thread joining is a little more confusing to
> describe, and deferred execution will not work correctly if the
> continuation future is ignored (the test case in the patch above fails
> when the continuation launch policy is deferred).
As far as we have a specific thread associated to it, I prefer to have
some one that takes car of joining it. I will see in which cases we can
call directly the continuation without using a new thread.
The experimental::future::then() has not this case as as async has been
removed. That means that there are no more blocking futures), but as
soon as you introduce async, the continuation is executed using the same
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net