void boost_();
private:
+ friend class Promise<T>;
template <class>
friend class futures::detail::FutureBase;
template <class>
#include <atomic>
#include <thread>
+#include <folly/executors/InlineExecutor.h>
#include <folly/futures/FutureException.h>
#include <folly/futures/detail/Core.h>
}
template <class T>
-Future<T> Promise<T>::getFuture() {
+SemiFuture<T> Promise<T>::getSemiFuture() {
throwIfRetrieved();
retrieved_ = true;
- return Future<T>(core_);
+ return SemiFuture<T>(core_);
+}
+
+template <class T>
+Future<T> Promise<T>::getFuture() {
+ // An InlineExecutor approximates the old behaviour of continuations
+ // running inine on setting the value of the promise.
+ return getSemiFuture().via(&InlineExecutor::instance());
}
template <class T>
Promise(Promise<T>&&) noexcept;
Promise& operator=(Promise<T>&&) noexcept;
+ /** Return a SemiFuture tied to the shared core state. This can be called only
+ once, thereafter FutureAlreadyRetrieved exception will be raised. */
+ SemiFuture<T> 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<T> getFuture();
/** Fulfill the Promise with an exception_wrapper */
#include <memory>
using namespace folly;
-using std::unique_ptr;
using std::string;
+using std::unique_ptr;
typedef FutureException eggs_t;
static eggs_t eggs("eggs");
EXPECT_TRUE(std::is_move_assignable<Promise<int>>::value);
}
+TEST(Promise, getSemiFuture) {
+ Promise<int> p;
+ SemiFuture<int> f = p.getSemiFuture();
+ EXPECT_FALSE(f.isReady());
+}
+
TEST(Promise, getFuture) {
Promise<int> p;
Future<int> f = p.getFuture();
p.setValue();
}
+TEST(Promise, setValueSemiFuture) {
+ Promise<int> fund;
+ auto ffund = fund.getSemiFuture();
+ fund.setValue(42);
+ EXPECT_EQ(42, ffund.value());
+
+ struct Foo {
+ string name;
+ int value;
+ };
+
+ Promise<Foo> 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<Foo>();
+ 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<unique_ptr<int>> mov;
+ auto fmov = mov.getSemiFuture();
+ mov.setValue(std::make_unique<int>(42));
+ unique_ptr<int> ptr = std::move(fmov.value());
+ EXPECT_EQ(42, *ptr);
+
+ Promise<Unit> v;
+ auto fv = v.getSemiFuture();
+ v.setValue();
+ EXPECT_TRUE(fv.isReady());
+}
+
TEST(Promise, setValue) {
Promise<int> fund;
auto ffund = fund.getFuture();
TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
Promise<int> p;
- auto f = SemiFuture<int>{p.getFuture()};
+ auto f = p.getSemiFuture();
EXPECT_FALSE(f.isReady());
p.setValue(42);
EXPECT_TRUE(f.isReady());
TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) {
Promise<int> p;
- auto f = SemiFuture<int>{p.getFuture()};
+ auto f = p.getSemiFuture();
EXPECT_THROW(f.value(), eggs_t);
}
folly::EventBase e;
Promise<int> p;
std::atomic<int> result{0};
- auto f = SemiFuture<int>{p.getFuture()};
+ auto f = p.getSemiFuture();
auto future = std::move(f).via(&e).then([&](int value) {
result = value;
return value;
folly::EventBase e;
Promise<int> p;
std::atomic<int> result{0};
- auto f = SemiFuture<int>{p.getFuture()};
+ auto f = p.getSemiFuture();
auto future = std::move(f).via(&e).then([&](int value) {
result = value;
return value;