Commit fb2a27a3 authored by Lee Howes's avatar Lee Howes Committed by Facebook Github Bot

Ensure that returning a semifuture from a continuation works correctly.

Summary: Returning a SemiFuture from a continuation should work by correctly checking the types and returning a folly::Future on the same executor as the original future that .then was applied to.

Reviewed By: yfeldblum

Differential Revision: D6597273

fbshipit-source-id: cf2016a344d4b29f1d31c1da20c89df5b4cfe64e
parent d0956208
......@@ -45,6 +45,24 @@ struct isFuture<Future<T>> : std::true_type {
typedef T Inner;
};
template <typename T>
struct isFutureOrSemiFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type;
using Return = Inner;
};
template <typename T>
struct isFutureOrSemiFuture<Future<T>> : std::true_type {
typedef T Inner;
using Return = Future<Inner>;
};
template <typename T>
struct isFutureOrSemiFuture<SemiFuture<T>> : std::true_type {
typedef T Inner;
using Return = SemiFuture<Inner>;
};
template <typename T>
struct isTry : std::false_type {};
......@@ -109,7 +127,7 @@ struct callableResult {
callableWith<F, Try<T>&&>::value,
detail::argResult<true, F, Try<T>&&>,
detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
typedef isFuture<typename Arg::Result> ReturnsFuture;
typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
};
......@@ -118,7 +136,7 @@ struct Extract : Extract<decltype(&L::operator())> { };
template <typename Class, typename R, typename... Args>
struct Extract<R(Class::*)(Args...) const> {
typedef isFuture<R> ReturnsFuture;
typedef isFutureOrSemiFuture<R> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
typedef typename ReturnsFuture::Inner RawReturn;
typedef typename ArgType<Args...>::FirstArg FirstArg;
......@@ -126,7 +144,7 @@ struct Extract<R(Class::*)(Args...) const> {
template <typename Class, typename R, typename... Args>
struct Extract<R(Class::*)(Args...)> {
typedef isFuture<R> ReturnsFuture;
typedef isFutureOrSemiFuture<R> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
typedef typename ReturnsFuture::Inner RawReturn;
typedef typename ArgType<Args...>::FirstArg FirstArg;
......@@ -134,7 +152,7 @@ struct Extract<R(Class::*)(Args...)> {
template <typename R, typename... Args>
struct Extract<R (*)(Args...)> {
typedef isFuture<R> ReturnsFuture;
typedef isFutureOrSemiFuture<R> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
typedef typename ReturnsFuture::Inner RawReturn;
typedef typename ArgType<Args...>::FirstArg FirstArg;
......@@ -142,7 +160,7 @@ struct Extract<R (*)(Args...)> {
template <typename R, typename... Args>
struct Extract<R (&)(Args...)> {
typedef isFuture<R> ReturnsFuture;
typedef isFutureOrSemiFuture<R> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
typedef typename ReturnsFuture::Inner RawReturn;
typedef typename ArgType<Args...>::FirstArg FirstArg;
......
......@@ -202,6 +202,44 @@ TEST(SemiFuture, MakeFutureFromSemiFuture) {
ASSERT_EQ(result, 42);
}
TEST(SemiFuture, MakeFutureFromSemiFutureReturnFuture) {
folly::EventBase e;
Promise<int> p;
int result{0};
auto f = p.getSemiFuture();
auto future = std::move(f).via(&e).then([&](int value) {
result = value;
return folly::makeFuture(std::move(value));
});
e.loop();
EXPECT_EQ(result, 0);
EXPECT_FALSE(future.isReady());
p.setValue(42);
e.loop();
EXPECT_TRUE(future.isReady());
ASSERT_EQ(future.value(), 42);
ASSERT_EQ(result, 42);
}
TEST(SemiFuture, MakeFutureFromSemiFutureReturnSemiFuture) {
folly::EventBase e;
Promise<int> p;
int result{0};
auto f = p.getSemiFuture();
auto future = std::move(f).via(&e).then([&](int value) {
result = value;
return folly::makeSemiFuture(std::move(value));
});
e.loop();
EXPECT_EQ(result, 0);
EXPECT_FALSE(future.isReady());
p.setValue(42);
e.loop();
EXPECT_TRUE(future.isReady());
ASSERT_EQ(future.value(), 42);
ASSERT_EQ(result, 42);
}
TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
folly::EventBase e;
Promise<int> p;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment