Move various attributes before the declaration to be compatible with MSVC
[folly.git] / folly / futures / helpers.h
index 138cfd475c58c10941084e27a987864c442581cd..3b0ef2995767ba05c325e3f2564a07d1d54a5b15 100644 (file)
@@ -37,20 +37,7 @@ namespace futures {
   /// The Timekeeper thread will be lazily created the first time it is
   /// needed. If your program never uses any timeouts or other time-based
   /// Futures you will pay no Timekeeper thread overhead.
-  Future<void> sleep(Duration, Timekeeper* = nullptr);
-
-  /// Create a Future chain from a sequence of callbacks. i.e.
-  ///
-  ///   f.then(a).then(b).then(c);
-  ///
-  /// where f is a Future<A> and the result of the chain is a Future<Z>
-  /// becomes
-  ///
-  ///   f.then(chain<A,Z>(a, b, c));
-  // If anyone figures how to get chain to deduce A and Z, I'll buy you a drink.
-  template <class A, class Z, class... Callbacks>
-  std::function<Future<Z>(Try<A>)>
-  chain(Callbacks... fns);
+  Future<Unit> sleep(Duration, Timekeeper* = nullptr);
 
   /**
    * Set func as the callback for each input Future and return a vector of
@@ -58,7 +45,8 @@ namespace futures {
    */
   template <class It, class F,
             class ItT = typename std::iterator_traits<It>::value_type,
-            class Result = decltype(std::declval<ItT>().then(std::declval<F>()))>
+            class Result
+      = typename decltype(std::declval<ItT>().then(std::declval<F>()))::value_type>
   std::vector<Future<Result>> map(It first, It last, F func);
 
   // Sugar for the most common case
@@ -68,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.
@@ -84,28 +72,20 @@ template <class T>
 Future<typename std::decay<T>::type> makeFuture(T&& t);
 
 /** Make a completed void Future. */
-Future<void> makeFuture();
+Future<Unit> makeFuture();
 
 /** Make a completed Future by executing a function. If the function throws
   we capture the exception, otherwise we capture the result. */
 template <class F>
-auto makeFutureWith(
-  F&& func,
-  typename std::enable_if<
-    !std::is_reference<F>::value, bool>::type sdf = false)
-  -> Future<decltype(func())>;
-
-template <class F>
-auto makeFutureWith(
-  F const& func)
-  -> Future<decltype(func())>;
+auto makeFutureWith(F&& func)
+    -> Future<typename Unit::Lift<decltype(func())>::type>;
 
 /// Make a failed Future from an exception_ptr.
 /// Because the Future's type cannot be inferred you have to specify it, e.g.
 ///
 ///   auto f = makeFuture<string>(std::current_exception());
 template <class T>
-Future<T> makeFuture(std::exception_ptr const& e) DEPRECATED;
+DEPRECATED Future<T> makeFuture(std::exception_ptr const& e);
 
 /// Make a failed Future from an exception_wrapper.
 template <class T>
@@ -127,11 +107,21 @@ Future<T> makeFuture(Try<T>&& t);
  * This is just syntactic sugar for makeFuture().via(executor)
  *
  * @param executor the Executor to call back on
+ * @param priority optionally, the priority to add with. Defaults to 0 which
+ * represents medium priority.
  *
  * @returns a void Future that will call back on the given executor
  */
-template <typename Executor>
-Future<void> via(Executor* executor);
+inline Future<Unit> 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
@@ -153,7 +143,7 @@ Future<std::vector<Try<
   typename std::iterator_traits<InputIterator>::value_type::value_type>>>
 collectAll(InputIterator first, InputIterator last);
 
-// Sugar for the most common case
+/// Sugar for the most common case
 template <class Collection>
 auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
   return collectAll(c.begin(), c.end());
@@ -164,7 +154,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);
 
@@ -177,12 +167,20 @@ Future<typename detail::CollectContext<
 >::result_type>
 collect(InputIterator first, InputIterator last);
 
-// Sugar for the most common case
+/// Sugar for the most common case
 template <class Collection>
 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.
@@ -195,7 +193,7 @@ Future<std::pair<
   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
 collectAny(InputIterator first, InputIterator last);
 
-// Sugar for the most common case
+/// Sugar for the most common case
 template <class Collection>
 auto collectAny(Collection&& c) -> decltype(collectAny(c.begin(), c.end())) {
   return collectAny(c.begin(), c.end());
@@ -213,13 +211,28 @@ Future<std::vector<std::pair<
   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
 collectN(InputIterator first, InputIterator last, size_t n);
 
-// Sugar for the most common case
+/// Sugar for the most common case
 template <class Collection>
 auto collectN(Collection&& c, size_t n)
     -> decltype(collectN(c.begin(), c.end(), n)) {
   return collectN(c.begin(), c.end(), n);
 }
 
+/** window creates up to n Futures using the values
+    in the collection, and then another Future for each Future
+    that completes
+
+    this is basically a sliding window of Futures of size n
+
+    func must return a Future for each value in input
+  */
+template <class Collection, class F,
+          class ItT = typename std::iterator_traits<
+            typename Collection::iterator>::value_type,
+          class Result = typename detail::resultOf<F, ItT&&>::value_type>
+std::vector<Future<Result>>
+window(Collection input, F func, size_t n);
+
 template <typename F, typename T, typename ItT>
 using MaybeTryArg = typename std::conditional<
   detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type;
@@ -233,17 +246,43 @@ 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,
-          class ItT = typename std::iterator_traits<It>::value_type::value_type,
-          class Arg = MaybeTryArg<F, T, ItT>>
-typename std::enable_if<!isFutureResult<F, T, Arg>::value, Future<T>>::type
-reduce(It first, It last, T initial, F func);
+template <class It, class T, class F>
+Future<T> reduce(It first, It last, T&& initial, F&& func);
+
+/// Sugar for the most common case
+template <class Collection, class T, class F>
+auto reduce(Collection&& c, T&& initial, F&& func)
+    -> decltype(reduce(c.begin(), c.end(), std::forward<T>(initial),
+                std::forward<F>(func))) {
+  return reduce(
+      c.begin(),
+      c.end(),
+      std::forward<T>(initial),
+      std::forward<F>(func));
+}
 
+/** 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>>
-typename std::enable_if<isFutureResult<F, T, Arg>::value, Future<T>>::type
-reduce(It first, It last, T initial, F func);
+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 folly
+} // namespace