Commit 9a797d91 authored by Hannes Roth's avatar Hannes Roth Committed by Praveen Kumar Ramakrishnan

(Wangle) Chaining reduce

Summary:
Oh, this is best of both worlds: D2015316

If your reduce is really cheap, just use `collect/CollectAll->reduce`.
Otherwise just use `reduce`. Great?

This one doesn't support returning Futures from `func`, but if you want
to do that, just use `reduce`.

Test Plan: Run all the tests.

Reviewed By: hans@fb.com

Subscribers: folly-diffs@, jsedgwick, yfeldblum, chalfant

FB internal diff: D2017238

Tasks: 6025252

Signature: t1:2017238:1430422971:c3471afa53239681f835624becf3c4a238204b70
parent a9c6c80d
...@@ -813,6 +813,20 @@ Future<T> reduce(It first, It last, T&& initial, F&& func) { ...@@ -813,6 +813,20 @@ Future<T> reduce(It first, It last, T&& initial, F&& func) {
return f; return f;
} }
template <class T>
template <class I, class F>
Future<I> Future<T>::reduce(I&& initial, F&& func) {
folly::MoveWrapper<I> minitial(std::move(initial));
folly::MoveWrapper<F> mfunc(std::move(func));
return then([minitial, mfunc](T& vals) mutable {
auto ret = std::move(*minitial);
for (auto& val : vals) {
ret = (*mfunc)(std::move(ret), std::move(val));
}
return ret;
});
}
template <class T> template <class T>
Future<T> Future<T>::within(Duration dur, Timekeeper* tk) { Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
return within(dur, TimedOut(), tk); return within(dur, TimedOut(), tk);
......
...@@ -375,6 +375,11 @@ class Future { ...@@ -375,6 +375,11 @@ class Future {
template <class F> template <class F>
Future<T> filter(F predicate); Future<T> filter(F predicate);
/// Like reduce, but works on a Future<std::vector<T / Try<T>>>, for example
/// the result of collect or collectAll
template <class I, class F>
Future<I> reduce(I&& initial, F&& func);
protected: protected:
typedef detail::Core<T>* corePtr; typedef detail::Core<T>* corePtr;
......
...@@ -1754,6 +1754,29 @@ TEST(Reduce, Basic) { ...@@ -1754,6 +1754,29 @@ TEST(Reduce, Basic) {
} }
} }
TEST(Reduce, Chain) {
auto makeFutures = [](int count) {
std::vector<Future<int>> fs;
for (int i = 1; i <= count; ++i) {
fs.emplace_back(makeFuture(i));
}
return fs;
};
{
auto f = collectAll(makeFutures(3)).reduce(0, [](int a, Try<int>&& b){
return a + *b;
});
EXPECT_EQ(6, f.get());
}
{
auto f = collect(makeFutures(3)).reduce(0, [](int a, int&& b){
return a + b;
});
EXPECT_EQ(6, f.get());
}
}
TEST(Map, Basic) { TEST(Map, Basic) {
Promise<int> p1; Promise<int> p1;
Promise<int> p2; Promise<int> p2;
......
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