Boost logo

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-17 13:55:12

Le 17/01/15 16:36, Vicente J. Botet Escriba a écrit :
> Le 17/01/15 15:36, Lee Clagett a écrit :
>> On Sat, Jan 17, 2015 at 8:48 AM, TONGARI J <tongari95_at_[hidden]
>> <mailto:tongari95_at_[hidden]>> wrote:
>> 2015-01-17 21:45 GMT+08:00 TONGARI J <tongari95_at_[hidden]
>> <mailto:tongari95_at_[hidden]>>:
>> Hi,
>> The sample code is here:
>> The boost::future adaption code is adapted from N4286.
> About this code
> template <class T, class Promise>
> void await_suspend(
> future<T> & t, std::experimental::resumable_handle<Promise> rh)
> {
> t.then([=](auto&& result) mutable {
> if (result.has_exception())
> rh.promise().set_exception(result.get_exception_ptr());
> rh();
> });
> } this will not suspend, as the result of t.then is ignored, and so it
> block on the destructor.
After the analysis below I should say, it should block, and currently
doesn't blocks :(

>> Tested with VS2015 preview.
>> If std::promise is passed, the code works fine.
>> Any clue why it hangs if boost::promise is passed?
>> Forgot to mention that it's compiled with Boost 1.57,
>> Thanks.
>> I found two bugs in this portion of boost::future last week, and I
>> have been meaning to post to trac and offer assistance in fixing.
> Please report Boost.Thread bugs as soon as possible. I'm really
> interested.
>> The first bug is in the .then() continuation - it is supposed to
>> block in this situation (according to the docs), just like
>> boost/std::async does if the future object is ignored.
> Agreed.
>> Instead, it continues unblocked.
> Hrr, I think that I see what you mean. The current implementation
> makes the shared state to block on the destructor, not the future
> itself, is that correct?
>> The second bug is a consequence of ignoring the returned future. The
>> call to .set_value() acquires the mutex, and invokes the continuation
>> on a separate thread.
> Right. The code is
> void launch_continuation(boost::unique_lock<boost::mutex>& ) {
> this->thr_ =
> thread(&future_async_continuation_shared_state::run, this);
> }
> Do you mean that I need to unlock before creating the thread? I could
> do it, but thread ensures that the function will not be called
> synchronously.
>> 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.
>> 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 :(

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at