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

Add explicit future detach operations

Summary: Detach by destruction is common, and for SemiFutures drops the continuation. We can instead make detach an explicit operation, parameterised optionally by an executor, and phase out implicit detach on destruction of SemiFuture.

Reviewed By: yfeldblum, andriigrynenko

Differential Revision: D20683652

fbshipit-source-id: 909d2ffcadbe71501edcddbf0847a9cb12aa3cce
parent d0df6d1f
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <folly/Traits.h> #include <folly/Traits.h>
#include <folly/detail/AsyncTrace.h> #include <folly/detail/AsyncTrace.h>
#include <folly/executors/ExecutorWithPriority.h> #include <folly/executors/ExecutorWithPriority.h>
#include <folly/executors/GlobalExecutor.h>
#include <folly/executors/InlineExecutor.h> #include <folly/executors/InlineExecutor.h>
#include <folly/executors/QueuedImmediateExecutor.h> #include <folly/executors/QueuedImmediateExecutor.h>
#include <folly/futures/detail/Core.h> #include <folly/futures/detail/Core.h>
...@@ -2581,6 +2582,16 @@ auto ensure(F&& f, Ensure&& ensure) { ...@@ -2581,6 +2582,16 @@ auto ensure(F&& f, Ensure&& ensure) {
}); });
} }
template <class T>
void detachOn(folly::Executor::KeepAlive<> exec, folly::SemiFuture<T>&& fut) {
std::move(fut).via(exec).detach();
}
template <class T>
void detachOnGlobalCPUExecutor(folly::SemiFuture<T>&& fut) {
detachOn(folly::getGlobalCPUExecutor(), std::move(fut));
}
} // namespace futures } // namespace futures
template <class Clock> template <class Clock>
......
...@@ -452,6 +452,12 @@ DeferredExecutor* getDeferredExecutor(SemiFuture<T>& future); ...@@ -452,6 +452,12 @@ DeferredExecutor* getDeferredExecutor(SemiFuture<T>& future);
template <typename T> template <typename T>
futures::detail::DeferredWrapper stealDeferredExecutor(SemiFuture<T>& future); futures::detail::DeferredWrapper stealDeferredExecutor(SemiFuture<T>& future);
} // namespace detail } // namespace detail
template <class T>
void detachOn(folly::Executor::KeepAlive<> exec, folly::SemiFuture<T>&& fut);
template <class T>
void detachOnGlobalCPUExecutor(folly::SemiFuture<T>&& fut);
} // namespace futures } // namespace futures
/// The interface (along with Future) for the consumer-side of a /// The interface (along with Future) for the consumer-side of a
...@@ -1923,6 +1929,12 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1923,6 +1929,12 @@ class Future : private futures::detail::FutureBase<T> {
friend Future<FT> futures::detail::convertFuture( friend Future<FT> futures::detail::convertFuture(
SemiFuture<FT>&& sf, SemiFuture<FT>&& sf,
const Future<FT>& f); const Future<FT>& f);
using Base::detach;
template <class T2>
friend void futures::detachOn(
folly::Executor::KeepAlive<> exec,
folly::SemiFuture<T2>&& fut);
}; };
/// A Timekeeper handles the details of keeping time and fulfilling delay /// A Timekeeper handles the details of keeping time and fulfilling delay
......
...@@ -1440,6 +1440,28 @@ TEST(Future, NoThrow) { ...@@ -1440,6 +1440,28 @@ TEST(Future, NoThrow) {
} }
} }
TEST(Future, DetachTest) {
folly::Baton<> b1, b2;
folly::ManualExecutor exec;
std::atomic<int> result(0);
folly::futures::detachOn(&exec, makeSemiFuture().deferValue([&](auto&&) {
result++;
b1.post();
}));
folly::futures::detachOnGlobalCPUExecutor(
makeSemiFuture().deferValue([&](auto&&) {
result++;
b2.post();
}));
exec.drain();
b1.wait();
b2.wait();
EXPECT_TRUE(result == 2);
}
#if FOLLY_FUTURE_USING_FIBER #if FOLLY_FUTURE_USING_FIBER
TEST(Future, BatonWait) { TEST(Future, BatonWait) {
......
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