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 10:36:45


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:
> https://gist.github.com/jamboree/3b8716ad1922749e77ae
>
> 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.

> 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,
> BOOST_THREAD_VERSION=4, x64
>
> 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 is self, 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 :(

Best,
Vicente



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