(Wangle) Chaining reduce
authorHannes Roth <hannesr@fb.com>
Fri, 1 May 2015 01:39:13 +0000 (18:39 -0700)
committerPraveen Kumar Ramakrishnan <praveenr@fb.com>
Tue, 12 May 2015 00:02:00 +0000 (17:02 -0700)
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

folly/futures/Future-inl.h
folly/futures/Future.h
folly/futures/test/FutureTest.cpp

index 39ac14b40f36d41a08c30e80aedb766fbbf3b4a4..289429dcc3c47ae6637ad7f410231c15305c30e8 100644 (file)
@@ -813,6 +813,20 @@ Future<T> reduce(It first, It last, T&& initial, F&& func) {
   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>
 Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
   return within(dur, TimedOut(), tk);
index 01e734e6b0bcf19a6ebe2bf04440be31a3e5d191..3acd7d46875003e5255de97cda31c2c7e7eda9a6 100644 (file)
@@ -375,6 +375,11 @@ class Future {
   template <class F>
   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:
   typedef detail::Core<T>* corePtr;
 
index 5b7be30673253d72ae4c64d6a9435c305191f441..faeb1da2fce190bc419962741d6c1c2a8958555b 100644 (file)
@@ -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) {
   Promise<int> p1;
   Promise<int> p2;