From: James Sedgwick <jsedgwick@fb.com>
Date: Tue, 21 Apr 2015 21:08:44 +0000 (-0700)
Subject: map()
X-Git-Tag: v0.36.0~19
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=82e3591a36262c575c2762d80d5d276e187208d7;p=folly.git

map()

Summary:
simple sugary syrup, best used in conjunction with collect/whenAll

Test Plan: unit

Reviewed By: hans@fb.com

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

FB internal diff: D1999047

Tasks: 6045623

Signature: t1:1999047:1429570631:62361bb43dc5489fe3d4eb31af404faf8a765402
---

diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h
index 7a2ffc2b..ea8368e8 100644
--- a/folly/futures/Future-inl.h
+++ b/folly/futures/Future-inl.h
@@ -1018,6 +1018,14 @@ namespace futures {
     };
   }
 
+  template <class It, class F, class ItT, class Result>
+  std::vector<Future<Result>> map(It first, It last, F func) {
+    std::vector<Future<Result>> results;
+    for (auto it = first; it != last; it++) {
+      results.push_back(it->then(func));
+    }
+    return results;
+  }
 }
 
 } // namespace folly
diff --git a/folly/futures/Future.h b/folly/futures/Future.h
index 90207dd8..26555753 100644
--- a/folly/futures/Future.h
+++ b/folly/futures/Future.h
@@ -181,6 +181,16 @@ namespace futures {
   template <class A, class Z, class... Callbacks>
   std::function<Future<Z>(Try<A>)>
   chain(Callbacks... fns);
+
+  /**
+   * Set func as the callback for each input Future and return a vector of
+   * Futures containing the results in the input order.
+   */
+  template <class It, class F,
+            class ItT = typename std::iterator_traits<It>::value_type,
+            class Result = decltype(std::declval<ItT>().then(std::declval<F>()))>
+  std::vector<Future<Result>> map(It first, It last, F func);
+
 }
 
 template <class T>
diff --git a/folly/futures/test/FutureTest.cpp b/folly/futures/test/FutureTest.cpp
index 82ac1f17..8efa6c64 100644
--- a/folly/futures/test/FutureTest.cpp
+++ b/folly/futures/test/FutureTest.cpp
@@ -1707,3 +1707,29 @@ TEST(Reduce, Basic) {
     EXPECT_EQ(6.3, f2.get());
   }
 }
+
+TEST(Map, Basic) {
+  Promise<int> p1;
+  Promise<int> p2;
+  Promise<int> p3;
+
+  std::vector<Future<int>> fs;
+  fs.push_back(p1.getFuture());
+  fs.push_back(p2.getFuture());
+  fs.push_back(p3.getFuture());
+
+  int c = 0;
+  auto fs2 = futures::map(fs.begin(), fs.end(), [&](int i){
+    c += i;
+  });
+
+  // Ensure we call the callbacks as the futures complete regardless of order
+  p2.setValue(1);
+  EXPECT_EQ(1, c);
+  p3.setValue(1);
+  EXPECT_EQ(2, c);
+  p1.setValue(1);
+  EXPECT_EQ(3, c);
+
+  EXPECT_TRUE(collect(fs2.begin(), fs2.end()).isReady());
+}