Details
-
Story
-
Status: Open
-
Major
-
Resolution: Unresolved
-
None
-
None
Description
Currently, Future::then will cut the "chain" short if it sees that a discard request is present:
template <typename T, typename X> void thenf(lambda::CallableOnce<Future<X>(const T&)>&& f, std::unique_ptr<Promise<X>> promise, const Future<T>& future) { if (future.isReady()) { if (future.hasDiscard()) { promise->discard(); // XXX } else { promise->associate(std::move(f)(future.get())); } } else if (future.isFailed()) { promise->fail(future.failure()); } else if (future.isDiscarded()) { promise->discard(); } }
However, this proves problematic because often the caller needs to control the discard semantics. An undiscardable helper was introduced to prevent discards from propagating in altogether, but this still leaves a problematic case. Consider the following code from the libevent SSL socket:
Future<std::shared_ptr<SocketImpl>> LibeventSSLSocketImpl::accept() { return accept_queue.get() .then([](const Future<std::shared_ptr<SocketImpl>>& impl) -> Future<std::shared_ptr<SocketImpl>> { return impl; }); }
Here, we do want the caller to be able to discard if the accept queue get is still pending. However, if the queue.get returns a READY future, we need to execute the .then continuation otherwise the socket gets dropped on the floor. A workaround is to use an explicit promise here with .onAny.
Ideally, there is a way to use .then where it doesn't make this discard decision. Either by moving .then to this behavior by default, or considering providing a way for the continuation to check for the discard request, or only letting the discard propagate when a continuation is asynchronous (i.e. returns a future), and leaving all synchronous continuations as undiscardable.
Attachments
Issue Links
- relates to
-
MESOS-7694 Discarding process::loop doesn't stop the loop
- Accepted