From: Hannes Roth Date: Fri, 1 May 2015 01:39:13 +0000 (-0700) Subject: (Wangle) Chaining reduce X-Git-Tag: v0.38.0~21 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9a797d917aaad916918e32d2dc7331b7208dda9e;p=folly.git (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 --- diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h index 39ac14b4..289429dc 100644 --- a/folly/futures/Future-inl.h +++ b/folly/futures/Future-inl.h @@ -813,6 +813,20 @@ Future reduce(It first, It last, T&& initial, F&& func) { return f; } +template +template +Future Future::reduce(I&& initial, F&& func) { + folly::MoveWrapper minitial(std::move(initial)); + folly::MoveWrapper 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 Future Future::within(Duration dur, Timekeeper* tk) { return within(dur, TimedOut(), tk); diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 01e734e6..3acd7d46 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -375,6 +375,11 @@ class Future { template Future filter(F predicate); + /// Like reduce, but works on a Future>>, for example + /// the result of collect or collectAll + template + Future reduce(I&& initial, F&& func); + protected: typedef detail::Core* corePtr; diff --git a/folly/futures/test/FutureTest.cpp b/folly/futures/test/FutureTest.cpp index 5b7be306..faeb1da2 100644 --- a/folly/futures/test/FutureTest.cpp +++ b/folly/futures/test/FutureTest.cpp @@ -1754,6 +1754,29 @@ TEST(Reduce, Basic) { } } +TEST(Reduce, Chain) { + auto makeFutures = [](int count) { + std::vector> 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&& 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) { Promise p1; Promise p2;