From: Lee Howes Date: Sat, 23 Dec 2017 03:29:14 +0000 (-0800) Subject: Add getSemiFuture to folly::Promise X-Git-Tag: v2017.12.25.00~2 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=48b9743d001e6c3dd3e66ef1dac702c9794833d7;p=folly.git Add getSemiFuture to folly::Promise Summary: Also deprecates folly::getFuture function. Reviewed By: yfeldblum Differential Revision: D6594299 fbshipit-source-id: 67435f35dca660da049cd8c505ee9a21424c0d2b --- diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 5eda2c34..2179623b 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -312,6 +312,7 @@ class SemiFuture : private futures::detail::FutureBase { void boost_(); private: + friend class Promise; template friend class futures::detail::FutureBase; template diff --git a/folly/futures/Promise-inl.h b/folly/futures/Promise-inl.h index 5c06d303..45e6929a 100644 --- a/folly/futures/Promise-inl.h +++ b/folly/futures/Promise-inl.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -85,10 +86,17 @@ void Promise::detach() { } template -Future Promise::getFuture() { +SemiFuture Promise::getSemiFuture() { throwIfRetrieved(); retrieved_ = true; - return Future(core_); + return SemiFuture(core_); +} + +template +Future Promise::getFuture() { + // An InlineExecutor approximates the old behaviour of continuations + // running inine on setting the value of the promise. + return getSemiFuture().via(&InlineExecutor::instance()); } template diff --git a/folly/futures/Promise.h b/folly/futures/Promise.h index 7bb58d1e..35965132 100644 --- a/folly/futures/Promise.h +++ b/folly/futures/Promise.h @@ -53,8 +53,15 @@ class Promise { Promise(Promise&&) noexcept; Promise& operator=(Promise&&) noexcept; + /** Return a SemiFuture tied to the shared core state. This can be called only + once, thereafter FutureAlreadyRetrieved exception will be raised. */ + SemiFuture getSemiFuture(); + /** Return a Future tied to the shared core state. This can be called only - once, thereafter Future already retrieved exception will be raised. */ + once, thereafter FutureAlreadyRetrieved exception will be raised. + NOTE: This function is deprecated. Please use getSemiFuture and pass the + appropriate executor to .via on the returned SemiFuture to get a + valid Future where necessary. */ Future getFuture(); /** Fulfill the Promise with an exception_wrapper */ diff --git a/folly/futures/test/PromiseTest.cpp b/folly/futures/test/PromiseTest.cpp index 509aa7aa..e5796d19 100644 --- a/folly/futures/test/PromiseTest.cpp +++ b/folly/futures/test/PromiseTest.cpp @@ -20,9 +20,9 @@ #include using namespace folly; -using std::unique_ptr; using std::string; +using std::unique_ptr; typedef FutureException eggs_t; static eggs_t eggs("eggs"); @@ -38,6 +38,12 @@ TEST(Promise, special) { EXPECT_TRUE(std::is_move_assignable>::value); } +TEST(Promise, getSemiFuture) { + Promise p; + SemiFuture f = p.getSemiFuture(); + EXPECT_FALSE(f.isReady()); +} + TEST(Promise, getFuture) { Promise p; Future f = p.getFuture(); @@ -49,6 +55,44 @@ TEST(Promise, setValueUnit) { p.setValue(); } +TEST(Promise, setValueSemiFuture) { + Promise fund; + auto ffund = fund.getSemiFuture(); + fund.setValue(42); + EXPECT_EQ(42, ffund.value()); + + struct Foo { + string name; + int value; + }; + + Promise pod; + auto fpod = pod.getSemiFuture(); + Foo f = {"the answer", 42}; + pod.setValue(f); + Foo f2 = fpod.value(); + EXPECT_EQ(f.name, f2.name); + EXPECT_EQ(f.value, f2.value); + + pod = Promise(); + fpod = pod.getSemiFuture(); + pod.setValue(std::move(f2)); + Foo f3 = fpod.value(); + EXPECT_EQ(f.name, f3.name); + EXPECT_EQ(f.value, f3.value); + + Promise> mov; + auto fmov = mov.getSemiFuture(); + mov.setValue(std::make_unique(42)); + unique_ptr ptr = std::move(fmov.value()); + EXPECT_EQ(42, *ptr); + + Promise v; + auto fv = v.getSemiFuture(); + v.setValue(); + EXPECT_TRUE(fv.isReady()); +} + TEST(Promise, setValue) { Promise fund; auto ffund = fund.getFuture(); diff --git a/folly/futures/test/SemiFutureTest.cpp b/folly/futures/test/SemiFutureTest.cpp index 7b927021..b5c059da 100644 --- a/folly/futures/test/SemiFutureTest.cpp +++ b/folly/futures/test/SemiFutureTest.cpp @@ -171,7 +171,7 @@ TEST(SemiFuture, MakeSemiFutureFromFutureWithValue) { TEST(SemiFuture, MakeSemiFutureFromReadyFuture) { Promise p; - auto f = SemiFuture{p.getFuture()}; + auto f = p.getSemiFuture(); EXPECT_FALSE(f.isReady()); p.setValue(42); EXPECT_TRUE(f.isReady()); @@ -179,7 +179,7 @@ TEST(SemiFuture, MakeSemiFutureFromReadyFuture) { TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) { Promise p; - auto f = SemiFuture{p.getFuture()}; + auto f = p.getSemiFuture(); EXPECT_THROW(f.value(), eggs_t); } @@ -187,7 +187,7 @@ TEST(SemiFuture, MakeFutureFromSemiFuture) { folly::EventBase e; Promise p; std::atomic result{0}; - auto f = SemiFuture{p.getFuture()}; + auto f = p.getSemiFuture(); auto future = std::move(f).via(&e).then([&](int value) { result = value; return value; @@ -206,7 +206,7 @@ TEST(SemiFuture, MakeFutureFromSemiFutureLValue) { folly::EventBase e; Promise p; std::atomic result{0}; - auto f = SemiFuture{p.getFuture()}; + auto f = p.getSemiFuture(); auto future = std::move(f).via(&e).then([&](int value) { result = value; return value;