Boost logo

Boost :

Subject: [boost] [future.then] Should deferred continuation respect status of original future?
From: Tomas Sturm (tomas.sturm_at_[hidden])
Date: 2017-05-31 07:38:38


Hi,

consider this code that wraps some library returning a future:

// some async library
boost::future<intermediate> DoLongAsyncTask() {
   return myPromise.get_future();
}

// intermediate translation layer
boost::future<result> GetResult() {
   return DoLongAsyncTask().then([] (boost::future<intermediate> f) {
            return TranslateToResult(f.get());
          });
}

// client event loop
void RunInClientContext() {
   auto myFuture = GetResult();
   while (stuffToDo()) {
     doStuff();
     if (SafeToCallFutureGetWithoutBlocking(myFuture))
       ProcessResult(myFuture.get());
   }
}

What should the implementation of 'SafeToCallFutureGetWithoutBlocking' be?
Normally, one would write something like:

myFuture.is_ready()
or
myFuture.wait_for(chrono::seconds(0)) != future_status::timeout

But this doesn't work in case the implementation of intermediate
translation layer calls .then
with launch::deferred! In Boost 1.63 the future returned from
.then(launch::deferred, ...)
is always deferred, so wait_for(...) always returns deferred no matter
what (and is_ready() always
returns false). In fact, there is no way to implement
'SafeToCallFutureGetWithoutBlocking' if
the translation is to happen in the context of the client
(launch::deferred).

Wouldn't it be more natural to respect the status of the original future
in this case?
The documentation is already very clear that the continuation is
executed only after the original
future is ready. So in case a client asks whether the continuation
future is ready, and the original
future is not ready yet, the call should forward to the original future
instead.

What I propose is this:

promise<int> p;
future<int> f1 = p.get_future();
future<int> f2 = f1.then(launch::deferred, [] (auto f) { return f.get(); });
assert(f2.wait_for(0) == future_status::timeout);
p.set_value(42);
assert(f2.wait_for(0) == future_status::deferred);

Is there any reason for the continuation future to not behave this way?

Regards
Tomas


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