Details
-
Improvement
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
None
-
None
Description
Previously, invoking Future::discard caused a future to transition
into the DISCARDED state which meant that any callbacks associated wit
such a transition (i.e., Future::onAny, Future::onDiscarded) got
executed _even if the computation associated with the future had not
yet completed_! This meant certain patterns where difficult if not all
together impossible. Consider:
ExpensiveResource* resource = new ExpensiveResource();
Future<int> future = function()
.then([=] ()
)
.onDiscarded([=] ()
);
future.discard();
In the above code, it's possible that the onDiscarded lambda would
execute concurrently with the lambda in the then! With the new
semantics, a discard is more advisorial: rather than transition a
future it instead allows a subsequent computation to decide whether or
not to cancel (or even begin) some computation. For example, the
Future::then implementation uses the "discard" information to decide
whether or not to execute the next lambda after the previous future
has been satisfied.
A few new helpers have been added to support this refactor:
Future::onDiscard(callback):
Adds a callback for when Future::discard was executed on this future.
Future::hasDiscard():
Checks to see if Future::discard was executed on this future.
Promise::discard():
Transitions this promises underlying future to DISCARDED.