Promise<T>::makeEmpty() and Future<T>::makeEmpty()
authorYedidya Feldblum <yfeldblum@fb.com>
Wed, 5 Jul 2017 16:38:08 +0000 (09:38 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 5 Jul 2017 16:52:20 +0000 (09:52 -0700)
Summary:
[Folly] `Promise<T>::makeEmpty()` and `Future<T>::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
folly/futures/Future.h
folly/futures/Promise-inl.h
folly/futures/Promise.h
folly/futures/test/FutureTest.cpp
folly/futures/test/PromiseTest.cpp

index 48083922a72db95500b3c6f041326ea1dce3c2fe..ab70c38d7bd436fdf8bc8253f0ed5320640320d9 100644 (file)
@@ -111,7 +111,7 @@ class CoreCallbackState {
   union {
     F func_;
   };
-  Promise<T> promise_{detail::EmptyConstruct{}};
+  Promise<T> promise_{Promise<T>::makeEmpty()};
 };
 
 template <typename T, typename F>
@@ -124,6 +124,11 @@ inline auto makeCoreCallbackState(Promise<T>&& p, F&& f) noexcept(
 }
 }
 
+template <class T>
+Future<T> Future<T>::makeEmpty() {
+  return Future<T>(detail::EmptyConstruct{});
+}
+
 template <class T>
 Future<T>::Future(Future<T>&& other) noexcept : core_(other.core_) {
   other.core_ = nullptr;
@@ -559,6 +564,10 @@ void Future<T>::raise(exception_wrapper exception) {
   core_->raise(std::move(exception));
 }
 
+template <class T>
+Future<T>::Future(detail::EmptyConstruct) noexcept
+    : core_(nullptr) {}
+
 // makeFuture
 
 template <class T>
index 87bb0cfe417cfcc735cc39aca9ae2ced9877527d..e5e1fbe82bf98bbd1ec04fd2ac7fe623410e77de 100644 (file)
@@ -45,6 +45,8 @@ class Future {
  public:
   typedef T value_type;
 
+  static Future<T> 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;
index 61d4d933e2e1234fc3cffb52d198613e4ecccf77..ee5f4d52b801ae22bf20df4858261ad450ac63de 100644 (file)
 
 namespace folly {
 
+template <class T>
+Promise<T> Promise<T>::makeEmpty() noexcept {
+  return Promise<T>(detail::EmptyConstruct{});
+}
+
 template <class T>
 Promise<T>::Promise() : retrieved_(false), core_(new detail::Core<T>())
 {}
index 75119129df82a69a65f2e8dc6298c0d16f0351e9..4a3f51c561e87b68f76f3cd22beb8cce7a5f6590 100644 (file)
@@ -34,6 +34,8 @@ class CoreCallbackState;
 template <class T>
 class Promise {
  public:
+  static Promise<T> makeEmpty() noexcept; // equivalent to moved-from
+
   Promise();
   ~Promise();
 
index 3322d2f4af52b5d40b028f99c2f5bbe138b0ddd2..e886a21a74bcb9e43244debb4bc30076a8c0f827 100644 (file)
@@ -40,6 +40,11 @@ static eggs_t eggs("eggs");
 
 // Future
 
+TEST(Future, makeEmpty) {
+  auto f = Future<int>::makeEmpty();
+  EXPECT_THROW(f.isReady(), NoState);
+}
+
 TEST(Future, futureDefaultCtor) {
   Future<Unit>();
 }
index 3673dc1d18f9c27fa8c8d12ec0b101f48c528167..224fc73fcdc60b76333bafaf6ba9e0f96edd4c48 100644 (file)
@@ -24,6 +24,11 @@ using std::string;
 typedef FutureException eggs_t;
 static eggs_t eggs("eggs");
 
+TEST(Promise, makeEmpty) {
+  auto p = Promise<int>::makeEmpty();
+  EXPECT_TRUE(p.isFulfilled());
+}
+
 TEST(Promise, special) {
   EXPECT_FALSE(std::is_copy_constructible<Promise<int>>::value);
   EXPECT_FALSE(std::is_copy_assignable<Promise<int>>::value);