Commit 15449325 authored by Lee Howes's avatar Lee Howes Committed by Facebook GitHub Bot

Have SemiFuture::within mark internal futures as consumed to avoid treating them as discarded.

Summary:
SemiFuture::within creates two valid SemiFutures and promptly overwrites them, both discarding valid SemiFutures and wasting the core allocation. It later drops the updated versions without directly consuming them, instead stealing the deferred executors.

This update initializes the two SemiFutures as empty, and safely terminates the chain with trivial callbacks so the SemiFutures can be treated as consumed.

Reviewed By: yfeldblum

Differential Revision: D21769500

fbshipit-source-id: eab13a78b17ecfc937b42c8d5e01e1292158d9ed
parent 8f13bf87
...@@ -2022,8 +2022,8 @@ SemiFuture<T>::within(HighResDuration dur, E e, Timekeeper* tk) && { ...@@ -2022,8 +2022,8 @@ SemiFuture<T>::within(HighResDuration dur, E e, Timekeeper* tk) && {
struct Context { struct Context {
explicit Context(E ex) : exception(std::move(ex)) {} explicit Context(E ex) : exception(std::move(ex)) {}
E exception; E exception;
SemiFuture<Unit> thisFuture; SemiFuture<Unit> thisFuture{SemiFuture<Unit>::makeEmpty()};
SemiFuture<Unit> afterFuture; SemiFuture<Unit> afterFuture{SemiFuture<Unit>::makeEmpty()};
Promise<T> promise; Promise<T> promise;
std::atomic<bool> token{false}; std::atomic<bool> token{false};
}; };
...@@ -2091,6 +2091,9 @@ SemiFuture<T>::within(HighResDuration dur, E e, Timekeeper* tk) && { ...@@ -2091,6 +2091,9 @@ SemiFuture<T>::within(HighResDuration dur, E e, Timekeeper* tk) && {
std::vector<folly::futures::detail::DeferredWrapper> nestedExecutors; std::vector<folly::futures::detail::DeferredWrapper> nestedExecutors;
nestedExecutors.emplace_back(ctx->thisFuture.stealDeferredExecutor()); nestedExecutors.emplace_back(ctx->thisFuture.stealDeferredExecutor());
nestedExecutors.emplace_back(ctx->afterFuture.stealDeferredExecutor()); nestedExecutors.emplace_back(ctx->afterFuture.stealDeferredExecutor());
// Set trivial callbacks to treat the futures as consumed
ctx->thisFuture.setCallback_([](Executor::KeepAlive<>&&, Try<Unit>&&) {});
ctx->afterFuture.setCallback_([](Executor::KeepAlive<>&&, Try<Unit>&&) {});
futures::detail::getDeferredExecutor(fut)->setNestedExecutors( futures::detail::getDeferredExecutor(fut)->setNestedExecutors(
std::move(nestedExecutors)); std::move(nestedExecutors));
return fut; return fut;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment