From e8527d2e4bfa7dc4538155f38f3374d997dd2f9b Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Sat, 8 Jul 2017 20:59:42 -0700 Subject: [PATCH] In-place construction for Future Summary: [Folly] In-place construction for `Future`. Using `in_place` as the first argument. Avoid constructing a contained object and then moving it into the `Future`, which may be more expensive, by providing an unambiguous way to specify perfect forwarding. And a matching overload of `makeFuture` for no particularly good reason. Differential Revision: D5362324 fbshipit-source-id: e612965f34ed0fae5fac17db631f7eab9984c696 --- folly/futures/Future-inl.h | 8 ++++++++ folly/futures/Future.h | 11 +++++++++-- folly/futures/detail/Core.h | 9 +++++++++ folly/futures/test/FutureTest.cpp | 5 +++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h index ab70c38d..84bf33a1 100644 --- a/folly/futures/Future-inl.h +++ b/folly/futures/Future-inl.h @@ -184,6 +184,14 @@ template Future::Future(typename std::enable_if::value>::type*) : core_(new detail::Core(Try(T()))) {} +template +template < + class... Args, + typename std::enable_if::value, int>:: + type> +Future::Future(in_place_t, Args&&... args) + : core_(new detail::Core(in_place, std::forward(args)...)) {} + template Future::~Future() { detach(); diff --git a/folly/futures/Future.h b/folly/futures/Future.h index e5e1fbe8..f4959ba7 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -25,10 +25,11 @@ #include #include -#include -#include #include +#include +#include #include +#include #include // boring predeclarations and details @@ -90,6 +91,12 @@ class Future { /* implicit */ Future( typename std::enable_if::value>::type* = nullptr); + template < + class... Args, + typename std::enable_if::value, int>:: + type = 0> + explicit Future(in_place_t, Args&&... args); + ~Future(); /** Return the reference to result. Should not be called if !isReady(). diff --git a/folly/futures/detail/Core.h b/folly/futures/detail/Core.h index 30d421c0..dc91729f 100644 --- a/folly/futures/detail/Core.h +++ b/folly/futures/detail/Core.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -87,6 +89,13 @@ class Core final { fsm_(State::OnlyResult), attached_(1) {} + template + explicit Core(in_place_t, Args&&... args) noexcept( + noexcept(::new (nullptr) T(std::declval()...))) + : result_(in_place, in_place, std::forward(args)...), + fsm_(State::OnlyResult), + attached_(1) {} + ~Core() { DCHECK(attached_ == 0); } diff --git a/folly/futures/test/FutureTest.cpp b/folly/futures/test/FutureTest.cpp index e886a21a..4dd3f2dc 100644 --- a/folly/futures/test/FutureTest.cpp +++ b/folly/futures/test/FutureTest.cpp @@ -810,6 +810,11 @@ TEST(Future, ImplicitConstructor) { //auto f2 = []() -> Future { }(); } +TEST(Future, InPlaceConstructor) { + auto f = Future>(in_place, 5, 3.2); + EXPECT_EQ(5, f.value().first); +} + TEST(Future, thenDynamic) { // folly::dynamic has a constructor that takes any T, this test makes // sure that we call the then lambda with folly::dynamic and not -- 2.34.1