From fbeb95acc305131b90693cdb782b7912cd80551d Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Wed, 5 Jul 2017 09:38:08 -0700 Subject: [PATCH] Promise::makeEmpty() and Future::makeEmpty() Summary: [Folly] `Promise::makeEmpty()` and `Future::makeEmpty()`. These can currently be done by creating, and then moving away from, regular promises and futures. But that allocates; this is semantically equivalent but more efficient. Differential Revision: D5368339 fbshipit-source-id: de054cfc75c701c5d39aac64d9a2949cd34b1896 --- folly/futures/Future-inl.h | 11 ++++++++++- folly/futures/Future.h | 4 ++++ folly/futures/Promise-inl.h | 5 +++++ folly/futures/Promise.h | 2 ++ folly/futures/test/FutureTest.cpp | 5 +++++ folly/futures/test/PromiseTest.cpp | 5 +++++ 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h index 48083922..ab70c38d 100644 --- a/folly/futures/Future-inl.h +++ b/folly/futures/Future-inl.h @@ -111,7 +111,7 @@ class CoreCallbackState { union { F func_; }; - Promise promise_{detail::EmptyConstruct{}}; + Promise promise_{Promise::makeEmpty()}; }; template @@ -124,6 +124,11 @@ inline auto makeCoreCallbackState(Promise&& p, F&& f) noexcept( } } +template +Future Future::makeEmpty() { + return Future(detail::EmptyConstruct{}); +} + template Future::Future(Future&& other) noexcept : core_(other.core_) { other.core_ = nullptr; @@ -559,6 +564,10 @@ void Future::raise(exception_wrapper exception) { core_->raise(std::move(exception)); } +template +Future::Future(detail::EmptyConstruct) noexcept + : core_(nullptr) {} + // makeFuture template diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 87bb0cfe..e5e1fbe8 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -45,6 +45,8 @@ class Future { public: typedef T value_type; + static Future makeEmpty(); // equivalent to moved-from + // not copyable Future(Future const&) = delete; Future& operator=(Future const&) = delete; @@ -481,6 +483,8 @@ class Future { explicit Future(corePtr obj) : core_(obj) {} + explicit Future(detail::EmptyConstruct) noexcept; + void detach(); void throwIfInvalid() const; diff --git a/folly/futures/Promise-inl.h b/folly/futures/Promise-inl.h index 61d4d933..ee5f4d52 100644 --- a/folly/futures/Promise-inl.h +++ b/folly/futures/Promise-inl.h @@ -24,6 +24,11 @@ namespace folly { +template +Promise Promise::makeEmpty() noexcept { + return Promise(detail::EmptyConstruct{}); +} + template Promise::Promise() : retrieved_(false), core_(new detail::Core()) {} diff --git a/folly/futures/Promise.h b/folly/futures/Promise.h index 75119129..4a3f51c5 100644 --- a/folly/futures/Promise.h +++ b/folly/futures/Promise.h @@ -34,6 +34,8 @@ class CoreCallbackState; template class Promise { public: + static Promise makeEmpty() noexcept; // equivalent to moved-from + Promise(); ~Promise(); diff --git a/folly/futures/test/FutureTest.cpp b/folly/futures/test/FutureTest.cpp index 3322d2f4..e886a21a 100644 --- a/folly/futures/test/FutureTest.cpp +++ b/folly/futures/test/FutureTest.cpp @@ -40,6 +40,11 @@ static eggs_t eggs("eggs"); // Future +TEST(Future, makeEmpty) { + auto f = Future::makeEmpty(); + EXPECT_THROW(f.isReady(), NoState); +} + TEST(Future, futureDefaultCtor) { Future(); } diff --git a/folly/futures/test/PromiseTest.cpp b/folly/futures/test/PromiseTest.cpp index 3673dc1d..224fc73f 100644 --- a/folly/futures/test/PromiseTest.cpp +++ b/folly/futures/test/PromiseTest.cpp @@ -24,6 +24,11 @@ using std::string; typedef FutureException eggs_t; static eggs_t eggs("eggs"); +TEST(Promise, makeEmpty) { + auto p = Promise::makeEmpty(); + EXPECT_TRUE(p.isFulfilled()); +} + TEST(Promise, special) { EXPECT_FALSE(std::is_copy_constructible>::value); EXPECT_FALSE(std::is_copy_assignable>::value); -- 2.34.1