Future::unit()
[folly.git] / folly / futures / helpers.h
index 775989e8a5b9295e9f0edd072eeaef0cd0650a31..c099f580b864d094b8b0ad0d2d945728e82c6740 100644 (file)
@@ -56,7 +56,7 @@ namespace futures {
     return map(c.begin(), c.end(), std::forward<F>(func));
   }
 
-}
+} // namespace futures
 
 /**
   Make a completed Future by moving in a value. e.g.
@@ -124,6 +124,13 @@ inline Future<void> via(
     Executor* executor,
     int8_t priority = Executor::MID_PRI);
 
+/// Execute a function via the given executor and return a future.
+/// This is semantically equivalent to via(executor).then(func), but
+/// easier to read and slightly more efficient.
+template <class Func>
+auto via(Executor*, Func func)
+  -> Future<typename isFuture<decltype(func())>::Inner>;
+
 /** When all the input Futures complete, the returned Future will complete.
   Errors do not cause early termination; this Future will always succeed
   after all its Futures have finished (whether successfully or with an
@@ -155,7 +162,7 @@ auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
 /// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
 /// The Futures are moved in, so your copies are invalid.
 template <typename... Fs>
-typename detail::VariadicContext<
+typename detail::CollectAllVariadicContext<
   typename std::decay<Fs>::type::value_type...>::type
 collectAll(Fs&&... fs);
 
@@ -174,6 +181,14 @@ auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
   return collect(c.begin(), c.end());
 }
 
+/// Like collectAll, but will short circuit on the first exception. Thus, the
+/// type of the returned Future is std::tuple<T1, T2, ...> instead of
+/// std::tuple<Try<T1>, Try<T2>, ...>
+template <typename... Fs>
+typename detail::CollectVariadicContext<
+  typename std::decay<Fs>::type::value_type...>::type
+collect(Fs&&... fs);
+
 /** The result is a pair of the index of the first Future to complete and
   the Try. If multiple Futures complete at the same time (or are already
   complete when passed in), the "winner" is chosen non-deterministically.
@@ -239,6 +254,9 @@ using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;
     The type of the final result is a Future of the type of the initial value.
 
     Func can either return a T, or a Future<T>
+
+    func is called in order of the input, see unorderedReduce if that is not
+    a requirement
   */
 template <class It, class T, class F>
 Future<T> reduce(It first, It last, T&& initial, F&& func);
@@ -255,4 +273,24 @@ auto reduce(Collection&& c, T&& initial, F&& func)
       std::forward<F>(func));
 }
 
-} // namespace folly
+/** like reduce, but calls func on finished futures as they complete
+    does NOT keep the order of the input
+  */
+template <class It, class T, class F,
+          class ItT = typename std::iterator_traits<It>::value_type::value_type,
+          class Arg = MaybeTryArg<F, T, ItT>>
+Future<T> unorderedReduce(It first, It last, T initial, F func);
+
+/// Sugar for the most common case
+template <class Collection, class T, class F>
+auto unorderedReduce(Collection&& c, T&& initial, F&& func)
+    -> decltype(unorderedReduce(c.begin(), c.end(), std::forward<T>(initial),
+                std::forward<F>(func))) {
+  return unorderedReduce(
+      c.begin(),
+      c.end(),
+      std::forward<T>(initial),
+      std::forward<F>(func));
+}
+
+} // namespace