Commit 1f6e3142 authored by Dor Gross's avatar Dor Gross Committed by Alecs King

Creating a flatten() method to get the inner Future<T> value out of a Future<Future<T>>.

Summary: Method will only be applicable for types of the form Future<Future<T>>, calling flatten() on a Future<T> where <T> != Future<R> for any <R> will result with a compile time error.

Test Plan: Added tests in FutureTest.cpp.

Reviewed By: hans@fb.com

Subscribers: ldbrandy, trunkagent, folly-diffs@, jsedgwick, yfeldblum, icanadi

FB internal diff: D1843581

Tasks: 6166903

Signature: t1:1843581:1424399517:7146924db3c238b77dd309f1d5916e44a7e81968
parent 6b9d347f
...@@ -98,6 +98,20 @@ void Future<T>::setCallback_(F&& func) { ...@@ -98,6 +98,20 @@ void Future<T>::setCallback_(F&& func) {
core_->setCallback(std::move(func)); core_->setCallback(std::move(func));
} }
// unwrap
template <class T>
template <class F>
typename std::enable_if<isFuture<F>::value,
Future<typename isFuture<T>::Inner>>::type
Future<T>::unwrap() {
return then([](Future<typename isFuture<T>::Inner> internal_future) {
return internal_future;
});
}
// then
// Variant: returns a value // Variant: returns a value
// e.g. f.then([](Try<T>&& t){ return t.value(); }); // e.g. f.then([](Try<T>&& t){ return t.value(); });
template <class T> template <class T>
......
...@@ -267,6 +267,13 @@ class Future { ...@@ -267,6 +267,13 @@ class Future {
/// value (moved out), or throws the exception. /// value (moved out), or throws the exception.
T getVia(DrivableExecutor* e); T getVia(DrivableExecutor* e);
/// Unwraps the case of a Future<Future<T>> instance, and returns a simple
/// Future<T> instance.
template <class F = T>
typename std::enable_if<isFuture<F>::value,
Future<typename isFuture<T>::Inner>>::type
unwrap();
/** When this Future has completed, execute func which is a function that /** When this Future has completed, execute func which is a function that
takes one of: takes one of:
(const) Try<T>&& (const) Try<T>&&
......
...@@ -1410,3 +1410,35 @@ TEST(Future, willEqual) { ...@@ -1410,3 +1410,35 @@ TEST(Future, willEqual) {
EXPECT_FALSE(f3.get()); EXPECT_FALSE(f3.get());
} }
} }
// Unwrap tests.
// A simple scenario for the unwrap call, when the promise was fulfilled
// before calling to unwrap.
TEST(Future, Unwrap_SimpleScenario) {
Future<int> encapsulated_future = makeFuture(5484);
Future<Future<int>> future = makeFuture(std::move(encapsulated_future));
EXPECT_EQ(5484, future.unwrap().value());
}
// Makes sure that unwrap() works when chaning Future's commands.
TEST(Future, Unwrap_ChainCommands) {
Future<Future<int>> future = makeFuture(makeFuture(5484));
auto unwrapped = future.unwrap().then([](int i){ return i; });
EXPECT_EQ(5484, unwrapped.value());
}
// Makes sure that the unwrap call also works when the promise was not yet
// fulfilled, and that the returned Future<T> becomes ready once the promise
// is fulfilled.
TEST(Future, Unwrap_FutureNotReady) {
Promise<Future<int>> p;
Future<Future<int>> future = p.getFuture();
Future<int> unwrapped = future.unwrap();
// Sanity - should not be ready before the promise is fulfilled.
ASSERT_FALSE(unwrapped.isReady());
// Fulfill the promise and make sure the unwrapped future is now ready.
p.setValue(makeFuture(5484));
ASSERT_TRUE(unwrapped.isReady());
EXPECT_EQ(5484, unwrapped.value());
}
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