Commit 312e7454 authored by James Sedgwick's avatar James Sedgwick Committed by Alecs King

when* -> collect*

Summary: title

Test Plan: tests

Reviewed By: hans@fb.com

Subscribers: laser-diffs@, trunkagent, mhl, rhe, fbcode-common-diffs@, chaoyc, search-fbcode-diffs@, hero-diffs@, zeus-diffs@, vikas, cold-storage-diffs@, rtgw-diffs@, unicorn-diffs@, targeting-diff-backend@, netego-diffs@, apollo-diffs@, everstore-dev@, zhuohuang, zhguo, jying, darshan, apodsiadlo, alikhtarov, folly-diffs@, wch, lins, tingy, jsedgwick, thom, yfeldblum, petchean, iaroslav, qhuang, gus, san, tomasz, pknowles, lyang, chalfant, paggarw, stevenkim

FB internal diff: D2003300

Tasks: 6025255

Signature: t1:2003300:1429659170:e18999cba45e8aa9019aa94f1f29732076a274ad
parent 5904c0ae
...@@ -33,7 +33,7 @@ typename std::vector< ...@@ -33,7 +33,7 @@ typename std::vector<
typename std::iterator_traits<InputIterator>::value_type()>::type> typename std::iterator_traits<InputIterator>::value_type()>::type>
>::type >::type
> >
whenN(InputIterator first, InputIterator last, size_t n) { collectN(InputIterator first, InputIterator last, size_t n) {
typedef typename std::result_of< typedef typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type Result; typename std::iterator_traits<InputIterator>::value_type()>::type Result;
assert(n > 0); assert(n > 0);
...@@ -96,7 +96,7 @@ typename std::enable_if< ...@@ -96,7 +96,7 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type, void typename std::iterator_traits<InputIterator>::value_type()>::type, void
>::value, std::vector<size_t>>::type >::value, std::vector<size_t>>::type
whenN(InputIterator first, InputIterator last, size_t n) { collectN(InputIterator first, InputIterator last, size_t n) {
assert(n > 0); assert(n > 0);
assert(n <= std::distance(first, last)); assert(n <= std::distance(first, last));
...@@ -160,7 +160,7 @@ typename std::vector< ...@@ -160,7 +160,7 @@ typename std::vector<
>::value, >::value,
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type>::type> typename std::iterator_traits<InputIterator>::value_type()>::type>::type>
inline whenAll(InputIterator first, InputIterator last) { inline collectAll(InputIterator first, InputIterator last) {
typedef typename std::result_of< typedef typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type Result; typename std::iterator_traits<InputIterator>::value_type()>::type Result;
size_t n = std::distance(first, last); size_t n = std::distance(first, last);
...@@ -191,7 +191,7 @@ typename std::enable_if< ...@@ -191,7 +191,7 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type, void typename std::iterator_traits<InputIterator>::value_type()>::type, void
>::value, void>::type >::value, void>::type
inline whenAll(InputIterator first, InputIterator last) { inline collectAll(InputIterator first, InputIterator last) {
forEach(first, last, [] (size_t id) {}); forEach(first, last, [] (size_t id) {});
} }
...@@ -206,8 +206,8 @@ typename std::enable_if< ...@@ -206,8 +206,8 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type> typename std::iterator_traits<InputIterator>::value_type()>::type>
>::type >::type
inline whenAny(InputIterator first, InputIterator last) { inline collectAny(InputIterator first, InputIterator last) {
auto result = whenN(first, last, 1); auto result = collectN(first, last, 1);
assert(result.size() == 1); assert(result.size() == 1);
return std::move(result[0]); return std::move(result[0]);
} }
...@@ -218,8 +218,8 @@ typename std::enable_if< ...@@ -218,8 +218,8 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type, void typename std::iterator_traits<InputIterator>::value_type()>::type, void
>::value, size_t>::type >::value, size_t>::type
inline whenAny(InputIterator first, InputIterator last) { inline collectAny(InputIterator first, InputIterator last) {
auto result = whenN(first, last, 1); auto result = collectN(first, last, 1);
assert(result.size() == 1); assert(result.size() == 1);
return std::move(result[0]); return std::move(result[0]);
} }
......
...@@ -42,10 +42,10 @@ typename std::vector< ...@@ -42,10 +42,10 @@ typename std::vector<
typename std::iterator_traits<InputIterator>::value_type()>::type> typename std::iterator_traits<InputIterator>::value_type()>::type>
>::type >::type
> >
inline whenN(InputIterator first, InputIterator last, size_t n); inline collectN(InputIterator first, InputIterator last, size_t n);
/** /**
* whenN specialization for functions returning void * collectN specialization for functions returning void
* *
* @param first Range of tasks to be scheduled * @param first Range of tasks to be scheduled
* @param last * @param last
...@@ -59,7 +59,7 @@ typename std::enable_if< ...@@ -59,7 +59,7 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type, void typename std::iterator_traits<InputIterator>::value_type()>::type, void
>::value, std::vector<size_t>>::type >::value, std::vector<size_t>>::type
inline whenN(InputIterator first, InputIterator last, size_t n); inline collectN(InputIterator first, InputIterator last, size_t n);
/** /**
* Schedules several tasks and blocks until all of these tasks are completed. * Schedules several tasks and blocks until all of these tasks are completed.
...@@ -82,10 +82,10 @@ typename std::vector< ...@@ -82,10 +82,10 @@ typename std::vector<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type>::type typename std::iterator_traits<InputIterator>::value_type()>::type>::type
> >
inline whenAll(InputIterator first, InputIterator last); inline collectAll(InputIterator first, InputIterator last);
/** /**
* whenAll specialization for functions returning void * collectAll specialization for functions returning void
* *
* @param first Range of tasks to be scheduled * @param first Range of tasks to be scheduled
* @param last * @param last
...@@ -96,7 +96,7 @@ typename std::enable_if< ...@@ -96,7 +96,7 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type, void typename std::iterator_traits<InputIterator>::value_type()>::type, void
>::value, void>::type >::value, void>::type
inline whenAll(InputIterator first, InputIterator last); inline collectAll(InputIterator first, InputIterator last);
/** /**
* Schedules several tasks and blocks until one of them is completed. * Schedules several tasks and blocks until one of them is completed.
...@@ -119,7 +119,7 @@ typename std::enable_if< ...@@ -119,7 +119,7 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type> typename std::iterator_traits<InputIterator>::value_type()>::type>
>::type >::type
inline whenAny(InputIterator first, InputIterator last); inline collectAny(InputIterator first, InputIterator last);
/** /**
* WhenAny specialization for functions returning void. * WhenAny specialization for functions returning void.
...@@ -135,7 +135,7 @@ typename std::enable_if< ...@@ -135,7 +135,7 @@ typename std::enable_if<
typename std::result_of< typename std::result_of<
typename std::iterator_traits<InputIterator>::value_type()>::type, void typename std::iterator_traits<InputIterator>::value_type()>::type, void
>::value, size_t>::type >::value, size_t>::type
inline whenAny(InputIterator first, InputIterator last); inline collectAny(InputIterator first, InputIterator last);
}} }}
......
...@@ -602,7 +602,7 @@ TEST(FiberManager, forEach) { ...@@ -602,7 +602,7 @@ TEST(FiberManager, forEach) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenN) { TEST(FiberManager, collectN) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -626,7 +626,7 @@ TEST(FiberManager, whenN) { ...@@ -626,7 +626,7 @@ TEST(FiberManager, whenN) {
); );
} }
auto results = whenN(funcs.begin(), funcs.end(), 2); auto results = collectN(funcs.begin(), funcs.end(), 2);
EXPECT_EQ(2, results.size()); EXPECT_EQ(2, results.size());
EXPECT_EQ(1, pendingFibers.size()); EXPECT_EQ(1, pendingFibers.size());
for (size_t i = 0; i < 2; ++i) { for (size_t i = 0; i < 2; ++i) {
...@@ -646,7 +646,7 @@ TEST(FiberManager, whenN) { ...@@ -646,7 +646,7 @@ TEST(FiberManager, whenN) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenNThrow) { TEST(FiberManager, collectNThrow) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -672,7 +672,7 @@ TEST(FiberManager, whenNThrow) { ...@@ -672,7 +672,7 @@ TEST(FiberManager, whenNThrow) {
} }
try { try {
whenN(funcs.begin(), funcs.end(), 2); collectN(funcs.begin(), funcs.end(), 2);
} catch (...) { } catch (...) {
EXPECT_EQ(1, pendingFibers.size()); EXPECT_EQ(1, pendingFibers.size());
} }
...@@ -690,7 +690,7 @@ TEST(FiberManager, whenNThrow) { ...@@ -690,7 +690,7 @@ TEST(FiberManager, whenNThrow) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenNVoid) { TEST(FiberManager, collectNVoid) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -713,7 +713,7 @@ TEST(FiberManager, whenNVoid) { ...@@ -713,7 +713,7 @@ TEST(FiberManager, whenNVoid) {
); );
} }
auto results = whenN(funcs.begin(), funcs.end(), 2); auto results = collectN(funcs.begin(), funcs.end(), 2);
EXPECT_EQ(2, results.size()); EXPECT_EQ(2, results.size());
EXPECT_EQ(1, pendingFibers.size()); EXPECT_EQ(1, pendingFibers.size());
} }
...@@ -730,7 +730,7 @@ TEST(FiberManager, whenNVoid) { ...@@ -730,7 +730,7 @@ TEST(FiberManager, whenNVoid) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenNVoidThrow) { TEST(FiberManager, collectNVoidThrow) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -755,7 +755,7 @@ TEST(FiberManager, whenNVoidThrow) { ...@@ -755,7 +755,7 @@ TEST(FiberManager, whenNVoidThrow) {
} }
try { try {
whenN(funcs.begin(), funcs.end(), 2); collectN(funcs.begin(), funcs.end(), 2);
} catch (...) { } catch (...) {
EXPECT_EQ(1, pendingFibers.size()); EXPECT_EQ(1, pendingFibers.size());
} }
...@@ -773,7 +773,7 @@ TEST(FiberManager, whenNVoidThrow) { ...@@ -773,7 +773,7 @@ TEST(FiberManager, whenNVoidThrow) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenAll) { TEST(FiberManager, collectAll) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -797,7 +797,7 @@ TEST(FiberManager, whenAll) { ...@@ -797,7 +797,7 @@ TEST(FiberManager, whenAll) {
); );
} }
auto results = whenAll(funcs.begin(), funcs.end()); auto results = collectAll(funcs.begin(), funcs.end());
EXPECT_TRUE(pendingFibers.empty()); EXPECT_TRUE(pendingFibers.empty());
for (size_t i = 0; i < 3; ++i) { for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(i*2+1, results[i]); EXPECT_EQ(i*2+1, results[i]);
...@@ -816,7 +816,7 @@ TEST(FiberManager, whenAll) { ...@@ -816,7 +816,7 @@ TEST(FiberManager, whenAll) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenAllVoid) { TEST(FiberManager, collectAllVoid) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -839,7 +839,7 @@ TEST(FiberManager, whenAllVoid) { ...@@ -839,7 +839,7 @@ TEST(FiberManager, whenAllVoid) {
); );
} }
whenAll(funcs.begin(), funcs.end()); collectAll(funcs.begin(), funcs.end());
EXPECT_TRUE(pendingFibers.empty()); EXPECT_TRUE(pendingFibers.empty());
} }
); );
...@@ -855,7 +855,7 @@ TEST(FiberManager, whenAllVoid) { ...@@ -855,7 +855,7 @@ TEST(FiberManager, whenAllVoid) {
loopController.loop(std::move(loopFunc)); loopController.loop(std::move(loopFunc));
} }
TEST(FiberManager, whenAny) { TEST(FiberManager, collectAny) {
std::vector<Promise<int>> pendingFibers; std::vector<Promise<int>> pendingFibers;
bool taskAdded = false; bool taskAdded = false;
...@@ -882,7 +882,7 @@ TEST(FiberManager, whenAny) { ...@@ -882,7 +882,7 @@ TEST(FiberManager, whenAny) {
); );
} }
auto result = whenAny(funcs.begin(), funcs.end()); auto result = collectAny(funcs.begin(), funcs.end());
EXPECT_EQ(2, pendingFibers.size()); EXPECT_EQ(2, pendingFibers.size());
EXPECT_EQ(2, result.first); EXPECT_EQ(2, result.first);
EXPECT_EQ(2*2+1, result.second); EXPECT_EQ(2*2+1, result.second);
...@@ -1255,7 +1255,7 @@ void testFiberLocal() { ...@@ -1255,7 +1255,7 @@ void testFiberLocal() {
local<Data>().value = 44; local<Data>().value = 44;
}; };
std::vector<std::function<void()>> tasks{task}; std::vector<std::function<void()>> tasks{task};
whenAny(tasks.begin(), tasks.end()); collectAny(tasks.begin(), tasks.end());
EXPECT_EQ(43, local<Data>().value); EXPECT_EQ(43, local<Data>().value);
}); });
......
...@@ -549,12 +549,12 @@ Future<void> via(Executor* executor) { ...@@ -549,12 +549,12 @@ Future<void> via(Executor* executor) {
template <typename... Fs> template <typename... Fs>
typename detail::VariadicContext< typename detail::VariadicContext<
typename std::decay<Fs>::type::value_type...>::type typename std::decay<Fs>::type::value_type...>::type
whenAll(Fs&&... fs) { collectAll(Fs&&... fs) {
auto ctx = auto ctx =
new detail::VariadicContext<typename std::decay<Fs>::type::value_type...>(); new detail::VariadicContext<typename std::decay<Fs>::type::value_type...>();
ctx->total = sizeof...(fs); ctx->total = sizeof...(fs);
auto f_saved = ctx->p.getFuture(); auto f_saved = ctx->p.getFuture();
detail::whenAllVariadicHelper(ctx, detail::collectAllVariadicHelper(ctx,
std::forward<typename std::decay<Fs>::type>(fs)...); std::forward<typename std::decay<Fs>::type>(fs)...);
return f_saved; return f_saved;
} }
...@@ -565,7 +565,7 @@ template <class InputIterator> ...@@ -565,7 +565,7 @@ template <class InputIterator>
Future< Future<
std::vector< std::vector<
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>> Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
whenAll(InputIterator first, InputIterator last) { collectAll(InputIterator first, InputIterator last) {
typedef typedef
typename std::iterator_traits<InputIterator>::value_type::value_type T; typename std::iterator_traits<InputIterator>::value_type::value_type T;
...@@ -727,7 +727,7 @@ Future< ...@@ -727,7 +727,7 @@ Future<
Try< Try<
typename typename
std::iterator_traits<InputIterator>::value_type::value_type> > > std::iterator_traits<InputIterator>::value_type::value_type> > >
whenAny(InputIterator first, InputIterator last) { collectAny(InputIterator first, InputIterator last) {
typedef typedef
typename std::iterator_traits<InputIterator>::value_type::value_type T; typename std::iterator_traits<InputIterator>::value_type::value_type T;
...@@ -750,7 +750,7 @@ whenAny(InputIterator first, InputIterator last) { ...@@ -750,7 +750,7 @@ whenAny(InputIterator first, InputIterator last) {
template <class InputIterator> template <class InputIterator>
Future<std::vector<std::pair<size_t, Try<typename Future<std::vector<std::pair<size_t, Try<typename
std::iterator_traits<InputIterator>::value_type::value_type>>>> std::iterator_traits<InputIterator>::value_type::value_type>>>>
whenN(InputIterator first, InputIterator last, size_t n) { collectN(InputIterator first, InputIterator last, size_t n) {
typedef typename typedef typename
std::iterator_traits<InputIterator>::value_type::value_type T; std::iterator_traits<InputIterator>::value_type::value_type T;
typedef std::vector<std::pair<size_t, Try<T>>> V; typedef std::vector<std::pair<size_t, Try<T>>> V;
...@@ -801,7 +801,7 @@ reduce(It first, It last, T initial, F func) { ...@@ -801,7 +801,7 @@ reduce(It first, It last, T initial, F func) {
typedef isTry<Arg> IsTry; typedef isTry<Arg> IsTry;
return whenAll(first, last) return collectAll(first, last)
.then([initial, func](std::vector<Try<ItT>>& vals) mutable { .then([initial, func](std::vector<Try<ItT>>& vals) mutable {
for (auto& val : vals) { for (auto& val : vals) {
initial = func(std::move(initial), initial = func(std::move(initial),
...@@ -828,7 +828,7 @@ reduce(It first, It last, T initial, F func) { ...@@ -828,7 +828,7 @@ reduce(It first, It last, T initial, F func) {
}); });
for (++first; first != last; ++first) { for (++first; first != last; ++first) {
f = whenAll(f, *first).then([func](std::tuple<Try<T>, Try<ItT>>& t) { f = collectAll(f, *first).then([func](std::tuple<Try<T>, Try<ItT>>& t) {
return func(std::move(std::get<0>(t).value()), return func(std::move(std::get<0>(t).value()),
// Either return a ItT&& or a Try<ItT>&& depending // Either return a ItT&& or a Try<ItT>&& depending
// on the type of the argument of func. // on the type of the argument of func.
...@@ -882,7 +882,7 @@ Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) { ...@@ -882,7 +882,7 @@ Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
template <class T> template <class T>
Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) { Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
return whenAll(*this, futures::sleep(dur, tk)) return collectAll(*this, futures::sleep(dur, tk))
.then([](std::tuple<Try<T>, Try<void>> tup) { .then([](std::tuple<Try<T>, Try<void>> tup) {
Try<T>& t = std::get<0>(tup); Try<T>& t = std::get<0>(tup);
return makeFuture<T>(std::move(t)); return makeFuture<T>(std::move(t));
...@@ -1019,7 +1019,7 @@ inline void Future<void>::getVia(DrivableExecutor* e) { ...@@ -1019,7 +1019,7 @@ inline void Future<void>::getVia(DrivableExecutor* e) {
template <class T> template <class T>
Future<bool> Future<T>::willEqual(Future<T>& f) { Future<bool> Future<T>::willEqual(Future<T>& f) {
return whenAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) { return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) { if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
return std::get<0>(t).value() == std::get<1>(t).value(); return std::get<0>(t).value() == std::get<1>(t).value();
} else { } else {
......
...@@ -641,7 +641,7 @@ Future<void> via(Executor* executor); ...@@ -641,7 +641,7 @@ Future<void> via(Executor* executor);
template <class InputIterator> template <class InputIterator>
Future<std::vector<Try< Future<std::vector<Try<
typename std::iterator_traits<InputIterator>::value_type::value_type>>> typename std::iterator_traits<InputIterator>::value_type::value_type>>>
whenAll(InputIterator first, InputIterator last); collectAll(InputIterator first, InputIterator last);
/// This version takes a varying number of Futures instead of an iterator. /// This version takes a varying number of Futures instead of an iterator.
/// The return type for (Future<T1>, Future<T2>, ...) input /// The return type for (Future<T1>, Future<T2>, ...) input
...@@ -650,9 +650,9 @@ whenAll(InputIterator first, InputIterator last); ...@@ -650,9 +650,9 @@ whenAll(InputIterator first, InputIterator last);
template <typename... Fs> template <typename... Fs>
typename detail::VariadicContext< typename detail::VariadicContext<
typename std::decay<Fs>::type::value_type...>::type typename std::decay<Fs>::type::value_type...>::type
whenAll(Fs&&... fs); collectAll(Fs&&... fs);
/// Like whenAll, but will short circuit on the first exception. Thus, the /// Like collectAll, but will short circuit on the first exception. Thus, the
/// type of the returned Future is std::vector<T> instead of /// type of the returned Future is std::vector<T> instead of
/// std::vector<Try<T>> /// std::vector<Try<T>>
template <class InputIterator> template <class InputIterator>
...@@ -671,7 +671,7 @@ template <class InputIterator> ...@@ -671,7 +671,7 @@ template <class InputIterator>
Future<std::pair< Future<std::pair<
size_t, size_t,
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>> Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
whenAny(InputIterator first, InputIterator last); collectAny(InputIterator first, InputIterator last);
/** when n Futures have completed, the Future completes with a vector of /** when n Futures have completed, the Future completes with a vector of
the index and Try of those n Futures (the indices refer to the original the index and Try of those n Futures (the indices refer to the original
...@@ -683,7 +683,7 @@ template <class InputIterator> ...@@ -683,7 +683,7 @@ template <class InputIterator>
Future<std::vector<std::pair< Future<std::vector<std::pair<
size_t, size_t,
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>> Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
whenN(InputIterator first, InputIterator last, size_t n); collectN(InputIterator first, InputIterator last, size_t n);
template <typename F, typename T, typename ItT> template <typename F, typename T, typename ItT>
using MaybeTryArg = typename std::conditional< using MaybeTryArg = typename std::conditional<
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Futures is a futures-based async framework inspired by [Twitter's Finagle](http://twitter.github.io/finagle/) (which is in scala), and (loosely) building upon the existing (but anemic) Futures code found in the C++11 standard ([`std::future`](http://en.cppreference.com/w/cpp/thread/future)) and [`boost::future`](http://www.boost.org/doc/libs/1_53_0/boost/thread/future.hpp) (especially >= 1.53.0). Although inspired by the std::future interface, it is not syntactically drop-in compatible because some ideas didn't translate well enough and we decided to break from the API. But semantically, it should be straightforward to translate from existing std::future code to Futures. Futures is a futures-based async framework inspired by [Twitter's Finagle](http://twitter.github.io/finagle/) (which is in scala), and (loosely) building upon the existing (but anemic) Futures code found in the C++11 standard ([`std::future`](http://en.cppreference.com/w/cpp/thread/future)) and [`boost::future`](http://www.boost.org/doc/libs/1_53_0/boost/thread/future.hpp) (especially >= 1.53.0). Although inspired by the std::future interface, it is not syntactically drop-in compatible because some ideas didn't translate well enough and we decided to break from the API. But semantically, it should be straightforward to translate from existing std::future code to Futures.
The primary semantic differences are that folly's Futures and Promises are not threadsafe; and as does `boost::future`, folly::Futures support continuing callbacks (`then()`) and there are helper methods `whenAll()` and `whenAny()` which are important compositional building blocks. The primary semantic differences are that folly's Futures and Promises are not threadsafe; and as does `boost::future`, folly::Futures support continuing callbacks (`then()`) and there are helper methods `collectAll()` and `collectAny()` which are important compositional building blocks.
## Brief Synopsis ## Brief Synopsis
...@@ -117,16 +117,16 @@ vector<Future<GetReply>> futs; ...@@ -117,16 +117,16 @@ vector<Future<GetReply>> futs;
for (auto& key : keys) { for (auto& key : keys) {
futs.push_back(mc.get(key)); futs.push_back(mc.get(key));
} }
auto all = whenAll(futs.begin(), futs.end()); auto all = collectAll(futs.begin(), futs.end());
vector<Future<GetReply>> futs; vector<Future<GetReply>> futs;
for (auto& key : keys) { for (auto& key : keys) {
futs.push_back(mc.get(key)); futs.push_back(mc.get(key));
} }
auto any = whenAny(futs.begin(), futs.end()); auto any = collectAny(futs.begin(), futs.end());
``` ```
`all` and `any` are Futures (for the exact type and usage see the header files). They will be complete when all/one of `futs` are complete, respectively. (There is also `whenN()` for when you need *some*.) `all` and `any` are Futures (for the exact type and usage see the header files). They will be complete when all/one of `futs` are complete, respectively. (There is also `collectN()` for when you need *some*.)
Second, we can attach callbacks to a Future, and chain them together monadically. An example will clarify: Second, we can attach callbacks to a Future, and chain them together monadically. An example will clarify:
......
...@@ -333,7 +333,7 @@ struct VariadicContext { ...@@ -333,7 +333,7 @@ struct VariadicContext {
template <typename... Ts, typename THead, typename... Fs> template <typename... Ts, typename THead, typename... Fs>
typename std::enable_if<sizeof...(Fs) == 0, void>::type typename std::enable_if<sizeof...(Fs) == 0, void>::type
whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) { collectAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
head.setCallback_([ctx](Try<typename THead::value_type>&& t) { head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t); std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
if (++ctx->count == ctx->total) { if (++ctx->count == ctx->total) {
...@@ -345,7 +345,7 @@ whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) { ...@@ -345,7 +345,7 @@ whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
template <typename... Ts, typename THead, typename... Fs> template <typename... Ts, typename THead, typename... Fs>
typename std::enable_if<sizeof...(Fs) != 0, void>::type typename std::enable_if<sizeof...(Fs) != 0, void>::type
whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) { collectAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
head.setCallback_([ctx](Try<typename THead::value_type>&& t) { head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t); std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
if (++ctx->count == ctx->total) { if (++ctx->count == ctx->total) {
...@@ -354,7 +354,7 @@ whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) { ...@@ -354,7 +354,7 @@ whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
} }
}); });
// template tail-recursion // template tail-recursion
whenAllVariadicHelper(ctx, std::forward<Fs>(tail)...); collectAllVariadicHelper(ctx, std::forward<Fs>(tail)...);
} }
template <typename T> template <typename T>
......
...@@ -689,7 +689,7 @@ TEST(Future, unwrap) { ...@@ -689,7 +689,7 @@ TEST(Future, unwrap) {
EXPECT_EQ(7, f.value()); EXPECT_EQ(7, f.value());
} }
TEST(Future, whenAll) { TEST(Future, collectAll) {
// returns a vector variant // returns a vector variant
{ {
vector<Promise<int>> promises(10); vector<Promise<int>> promises(10);
...@@ -698,7 +698,7 @@ TEST(Future, whenAll) { ...@@ -698,7 +698,7 @@ TEST(Future, whenAll) {
for (auto& p : promises) for (auto& p : promises)
futures.push_back(p.getFuture()); futures.push_back(p.getFuture());
auto allf = whenAll(futures.begin(), futures.end()); auto allf = collectAll(futures.begin(), futures.end());
random_shuffle(promises.begin(), promises.end()); random_shuffle(promises.begin(), promises.end());
for (auto& p : promises) { for (auto& p : promises) {
...@@ -721,7 +721,7 @@ TEST(Future, whenAll) { ...@@ -721,7 +721,7 @@ TEST(Future, whenAll) {
for (auto& p : promises) for (auto& p : promises)
futures.push_back(p.getFuture()); futures.push_back(p.getFuture());
auto allf = whenAll(futures.begin(), futures.end()); auto allf = collectAll(futures.begin(), futures.end());
promises[0].setValue(42); promises[0].setValue(42);
...@@ -753,7 +753,7 @@ TEST(Future, whenAll) { ...@@ -753,7 +753,7 @@ TEST(Future, whenAll) {
for (auto& p : promises) for (auto& p : promises)
futures.push_back(p.getFuture()); futures.push_back(p.getFuture());
auto allf = whenAll(futures.begin(), futures.end()) auto allf = collectAll(futures.begin(), futures.end())
.then([](Try<vector<Try<void>>>&& ts) { .then([](Try<vector<Try<void>>>&& ts) {
for (auto& f : ts.value()) for (auto& f : ts.value())
f.value(); f.value();
...@@ -924,7 +924,7 @@ TEST(Future, collectNotDefaultConstructible) { ...@@ -924,7 +924,7 @@ TEST(Future, collectNotDefaultConstructible) {
} }
} }
TEST(Future, whenAny) { TEST(Future, collectAny) {
{ {
vector<Promise<int>> promises(10); vector<Promise<int>> promises(10);
vector<Future<int>> futures; vector<Future<int>> futures;
...@@ -936,7 +936,7 @@ TEST(Future, whenAny) { ...@@ -936,7 +936,7 @@ TEST(Future, whenAny) {
EXPECT_FALSE(f.isReady()); EXPECT_FALSE(f.isReady());
} }
auto anyf = whenAny(futures.begin(), futures.end()); auto anyf = collectAny(futures.begin(), futures.end());
/* futures were moved in, so these are invalid now */ /* futures were moved in, so these are invalid now */
EXPECT_FALSE(anyf.isReady()); EXPECT_FALSE(anyf.isReady());
...@@ -964,7 +964,7 @@ TEST(Future, whenAny) { ...@@ -964,7 +964,7 @@ TEST(Future, whenAny) {
EXPECT_FALSE(f.isReady()); EXPECT_FALSE(f.isReady());
} }
auto anyf = whenAny(futures.begin(), futures.end()); auto anyf = collectAny(futures.begin(), futures.end());
EXPECT_FALSE(anyf.isReady()); EXPECT_FALSE(anyf.isReady());
...@@ -981,7 +981,7 @@ TEST(Future, whenAny) { ...@@ -981,7 +981,7 @@ TEST(Future, whenAny) {
for (auto& p : promises) for (auto& p : promises)
futures.push_back(p.getFuture()); futures.push_back(p.getFuture());
auto anyf = whenAny(futures.begin(), futures.end()) auto anyf = collectAny(futures.begin(), futures.end())
.then([](pair<size_t, Try<int>> p) { .then([](pair<size_t, Try<int>> p) {
EXPECT_EQ(42, p.second.value()); EXPECT_EQ(42, p.second.value());
}); });
...@@ -998,7 +998,7 @@ TEST(when, already_completed) { ...@@ -998,7 +998,7 @@ TEST(when, already_completed) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
fs.push_back(makeFuture()); fs.push_back(makeFuture());
whenAll(fs.begin(), fs.end()) collectAll(fs.begin(), fs.end())
.then([&](vector<Try<void>> ts) { .then([&](vector<Try<void>> ts) {
EXPECT_EQ(fs.size(), ts.size()); EXPECT_EQ(fs.size(), ts.size());
}); });
...@@ -1008,14 +1008,14 @@ TEST(when, already_completed) { ...@@ -1008,14 +1008,14 @@ TEST(when, already_completed) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
fs.push_back(makeFuture(i)); fs.push_back(makeFuture(i));
whenAny(fs.begin(), fs.end()) collectAny(fs.begin(), fs.end())
.then([&](pair<size_t, Try<int>> p) { .then([&](pair<size_t, Try<int>> p) {
EXPECT_EQ(p.first, p.second.value()); EXPECT_EQ(p.first, p.second.value());
}); });
} }
} }
TEST(when, whenN) { TEST(when, collectN) {
vector<Promise<void>> promises(10); vector<Promise<void>> promises(10);
vector<Future<void>> futures; vector<Future<void>> futures;
...@@ -1024,7 +1024,7 @@ TEST(when, whenN) { ...@@ -1024,7 +1024,7 @@ TEST(when, whenN) {
bool flag = false; bool flag = false;
size_t n = 3; size_t n = 3;
whenN(futures.begin(), futures.end(), n) collectN(futures.begin(), futures.end(), n)
.then([&](vector<pair<size_t, Try<void>>> v) { .then([&](vector<pair<size_t, Try<void>>> v) {
flag = true; flag = true;
EXPECT_EQ(n, v.size()); EXPECT_EQ(n, v.size());
...@@ -1055,7 +1055,7 @@ TEST(when, small_vector) { ...@@ -1055,7 +1055,7 @@ TEST(when, small_vector) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
futures.push_back(makeFuture()); futures.push_back(makeFuture());
auto anyf = whenAny(futures.begin(), futures.end()); auto anyf = collectAny(futures.begin(), futures.end());
} }
{ {
...@@ -1064,17 +1064,17 @@ TEST(when, small_vector) { ...@@ -1064,17 +1064,17 @@ TEST(when, small_vector) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
futures.push_back(makeFuture()); futures.push_back(makeFuture());
auto allf = whenAll(futures.begin(), futures.end()); auto allf = collectAll(futures.begin(), futures.end());
} }
} }
TEST(Future, whenAllVariadic) { TEST(Future, collectAllVariadic) {
Promise<bool> pb; Promise<bool> pb;
Promise<int> pi; Promise<int> pi;
Future<bool> fb = pb.getFuture(); Future<bool> fb = pb.getFuture();
Future<int> fi = pi.getFuture(); Future<int> fi = pi.getFuture();
bool flag = false; bool flag = false;
whenAll(std::move(fb), std::move(fi)) collectAll(std::move(fb), std::move(fi))
.then([&](std::tuple<Try<bool>, Try<int>> tup) { .then([&](std::tuple<Try<bool>, Try<int>> tup) {
flag = true; flag = true;
EXPECT_TRUE(std::get<0>(tup).hasValue()); EXPECT_TRUE(std::get<0>(tup).hasValue());
...@@ -1088,13 +1088,13 @@ TEST(Future, whenAllVariadic) { ...@@ -1088,13 +1088,13 @@ TEST(Future, whenAllVariadic) {
EXPECT_TRUE(flag); EXPECT_TRUE(flag);
} }
TEST(Future, whenAllVariadicReferences) { TEST(Future, collectAllVariadicReferences) {
Promise<bool> pb; Promise<bool> pb;
Promise<int> pi; Promise<int> pi;
Future<bool> fb = pb.getFuture(); Future<bool> fb = pb.getFuture();
Future<int> fi = pi.getFuture(); Future<int> fi = pi.getFuture();
bool flag = false; bool flag = false;
whenAll(fb, fi) collectAll(fb, fi)
.then([&](std::tuple<Try<bool>, Try<int>> tup) { .then([&](std::tuple<Try<bool>, Try<int>> tup) {
flag = true; flag = true;
EXPECT_TRUE(std::get<0>(tup).hasValue()); EXPECT_TRUE(std::get<0>(tup).hasValue());
...@@ -1108,9 +1108,9 @@ TEST(Future, whenAllVariadicReferences) { ...@@ -1108,9 +1108,9 @@ TEST(Future, whenAllVariadicReferences) {
EXPECT_TRUE(flag); EXPECT_TRUE(flag);
} }
TEST(Future, whenAll_none) { TEST(Future, collectAll_none) {
vector<Future<int>> fs; vector<Future<int>> fs;
auto f = whenAll(fs.begin(), fs.end()); auto f = collectAll(fs.begin(), fs.end());
EXPECT_TRUE(f.isReady()); EXPECT_TRUE(f.isReady());
} }
...@@ -1155,13 +1155,13 @@ TEST(Future, waitImmediate) { ...@@ -1155,13 +1155,13 @@ TEST(Future, waitImmediate) {
vector<Future<void>> v_f; vector<Future<void>> v_f;
v_f.push_back(makeFuture()); v_f.push_back(makeFuture());
v_f.push_back(makeFuture()); v_f.push_back(makeFuture());
auto done_v_f = whenAll(v_f.begin(), v_f.end()).wait().value(); auto done_v_f = collectAll(v_f.begin(), v_f.end()).wait().value();
EXPECT_EQ(2, done_v_f.size()); EXPECT_EQ(2, done_v_f.size());
vector<Future<bool>> v_fb; vector<Future<bool>> v_fb;
v_fb.push_back(makeFuture(true)); v_fb.push_back(makeFuture(true));
v_fb.push_back(makeFuture(false)); v_fb.push_back(makeFuture(false));
auto fut = whenAll(v_fb.begin(), v_fb.end()); auto fut = collectAll(v_fb.begin(), v_fb.end());
auto done_v_fb = std::move(fut.wait().value()); auto done_v_fb = std::move(fut.wait().value());
EXPECT_EQ(2, done_v_fb.size()); EXPECT_EQ(2, done_v_fb.size());
} }
...@@ -1261,7 +1261,7 @@ TEST(Future, waitWithDuration) { ...@@ -1261,7 +1261,7 @@ TEST(Future, waitWithDuration) {
vector<Future<bool>> v_fb; vector<Future<bool>> v_fb;
v_fb.push_back(makeFuture(true)); v_fb.push_back(makeFuture(true));
v_fb.push_back(makeFuture(false)); v_fb.push_back(makeFuture(false));
auto f = whenAll(v_fb.begin(), v_fb.end()); auto f = collectAll(v_fb.begin(), v_fb.end());
f.wait(milliseconds(1)); f.wait(milliseconds(1));
EXPECT_TRUE(f.isReady()); EXPECT_TRUE(f.isReady());
EXPECT_EQ(2, f.value().size()); EXPECT_EQ(2, f.value().size());
...@@ -1272,7 +1272,7 @@ TEST(Future, waitWithDuration) { ...@@ -1272,7 +1272,7 @@ TEST(Future, waitWithDuration) {
Promise<bool> p2; Promise<bool> p2;
v_fb.push_back(p1.getFuture()); v_fb.push_back(p1.getFuture());
v_fb.push_back(p2.getFuture()); v_fb.push_back(p2.getFuture());
auto f = whenAll(v_fb.begin(), v_fb.end()); auto f = collectAll(v_fb.begin(), v_fb.end());
f.wait(milliseconds(1)); f.wait(milliseconds(1));
EXPECT_FALSE(f.isReady()); EXPECT_FALSE(f.isReady());
p1.setValue(true); p1.setValue(true);
...@@ -1484,7 +1484,7 @@ TEST(Future, t5506504) { ...@@ -1484,7 +1484,7 @@ TEST(Future, t5506504) {
for (auto& p : *promises) p.setValue(); for (auto& p : *promises) p.setValue();
}); });
return whenAll(futures.begin(), futures.end()); return collectAll(futures.begin(), futures.end());
}; };
fn().wait(); fn().wait();
......
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