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@gmail.com> wrote:
2015-01-17 21:45 GMT+08:00 TONGARI J <tongari95@gmail.com>:
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 :(

Vicente
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 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 :(