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
Future<T>::Future(typename std::enable_if<std::is_same<Unit, T2>::value>::type*)
: core_(new detail::Core<T>(Try<T>(T()))) {}
+template <class T>
+template <
+ class... Args,
+ typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
+ type>
+Future<T>::Future(in_place_t, Args&&... args)
+ : core_(new detail::Core<T>(in_place, std::forward<Args>(args)...)) {}
+
template <class T>
Future<T>::~Future() {
detach();
#include <folly/Optional.h>
#include <folly/Portability.h>
-#include <folly/futures/DrivableExecutor.h>
-#include <folly/futures/Promise.h>
#include <folly/Try.h>
+#include <folly/Utility.h>
+#include <folly/futures/DrivableExecutor.h>
#include <folly/futures/FutureException.h>
+#include <folly/futures/Promise.h>
#include <folly/futures/detail/Types.h>
// boring predeclarations and details
/* implicit */ Future(
typename std::enable_if<std::is_same<Unit, T2>::value>::type* = nullptr);
+ template <
+ class... Args,
+ typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
+ type = 0>
+ explicit Future(in_place_t, Args&&... args);
+
~Future();
/** Return the reference to result. Should not be called if !isReady().
#include <atomic>
#include <mutex>
#include <stdexcept>
+#include <utility>
#include <vector>
#include <folly/Executor.h>
#include <folly/Optional.h>
#include <folly/ScopeGuard.h>
#include <folly/Try.h>
+#include <folly/Utility.h>
#include <folly/futures/FutureException.h>
#include <folly/futures/detail/FSM.h>
fsm_(State::OnlyResult),
attached_(1) {}
+ template <typename... Args>
+ explicit Core(in_place_t, Args&&... args) noexcept(
+ noexcept(::new (nullptr) T(std::declval<Args&&>()...)))
+ : result_(in_place, in_place, std::forward<Args>(args)...),
+ fsm_(State::OnlyResult),
+ attached_(1) {}
+
~Core() {
DCHECK(attached_ == 0);
}
//auto f2 = []() -> Future<Unit> { }();
}
+TEST(Future, InPlaceConstructor) {
+ auto f = Future<std::pair<int, double>>(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