folly::via(Executor*, Func)
[folly.git] / folly / futures / helpers.h
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17
18 #include <folly/futures/Future.h>
19
20 namespace folly {
21
22 /// This namespace is for utility functions that would usually be static
23 /// members of Future, except they don't make sense there because they don't
24 /// depend on the template type (rather, on the type of their arguments in
25 /// some cases). This is the least-bad naming scheme we could think of. Some
26 /// of the functions herein have really-likely-to-collide names, like "map"
27 /// and "sleep".
28 namespace futures {
29   /// Returns a Future that will complete after the specified duration. The
30   /// Duration typedef of a `std::chrono` duration type indicates the
31   /// resolution you can expect to be meaningful (milliseconds at the time of
32   /// writing). Normally you wouldn't need to specify a Timekeeper, we will
33   /// use the global futures timekeeper (we run a thread whose job it is to
34   /// keep time for futures timeouts) but we provide the option for power
35   /// users.
36   ///
37   /// The Timekeeper thread will be lazily created the first time it is
38   /// needed. If your program never uses any timeouts or other time-based
39   /// Futures you will pay no Timekeeper thread overhead.
40   Future<void> sleep(Duration, Timekeeper* = nullptr);
41
42   /**
43    * Set func as the callback for each input Future and return a vector of
44    * Futures containing the results in the input order.
45    */
46   template <class It, class F,
47             class ItT = typename std::iterator_traits<It>::value_type,
48             class Result
49       = typename decltype(std::declval<ItT>().then(std::declval<F>()))::value_type>
50   std::vector<Future<Result>> map(It first, It last, F func);
51
52   // Sugar for the most common case
53   template <class Collection, class F>
54   auto map(Collection&& c, F&& func)
55       -> decltype(map(c.begin(), c.end(), func)) {
56     return map(c.begin(), c.end(), std::forward<F>(func));
57   }
58
59 } // namespace futures
60
61 /**
62   Make a completed Future by moving in a value. e.g.
63
64     string foo = "foo";
65     auto f = makeFuture(std::move(foo));
66
67   or
68
69     auto f = makeFuture<string>("foo");
70 */
71 template <class T>
72 Future<typename std::decay<T>::type> makeFuture(T&& t);
73
74 /** Make a completed void Future. */
75 Future<void> makeFuture();
76
77 /** Make a completed Future by executing a function. If the function throws
78   we capture the exception, otherwise we capture the result. */
79 template <class F>
80 auto makeFutureWith(
81   F&& func,
82   typename std::enable_if<
83     !std::is_reference<F>::value, bool>::type sdf = false)
84   -> Future<decltype(func())>;
85
86 template <class F>
87 auto makeFutureWith(
88   F const& func)
89   -> Future<decltype(func())>;
90
91 /// Make a failed Future from an exception_ptr.
92 /// Because the Future's type cannot be inferred you have to specify it, e.g.
93 ///
94 ///   auto f = makeFuture<string>(std::current_exception());
95 template <class T>
96 Future<T> makeFuture(std::exception_ptr const& e) DEPRECATED;
97
98 /// Make a failed Future from an exception_wrapper.
99 template <class T>
100 Future<T> makeFuture(exception_wrapper ew);
101
102 /** Make a Future from an exception type E that can be passed to
103   std::make_exception_ptr(). */
104 template <class T, class E>
105 typename std::enable_if<std::is_base_of<std::exception, E>::value,
106                         Future<T>>::type
107 makeFuture(E const& e);
108
109 /** Make a Future out of a Try */
110 template <class T>
111 Future<T> makeFuture(Try<T>&& t);
112
113 /*
114  * Return a new Future that will call back on the given Executor.
115  * This is just syntactic sugar for makeFuture().via(executor)
116  *
117  * @param executor the Executor to call back on
118  * @param priority optionally, the priority to add with. Defaults to 0 which
119  * represents medium priority.
120  *
121  * @returns a void Future that will call back on the given executor
122  */
123 inline Future<void> via(
124     Executor* executor,
125     int8_t priority = Executor::MID_PRI);
126
127 /// Execute a function via the given executor and return a future.
128 /// This is semantically equivalent to via(executor).then(func), but
129 /// easier to read and slightly more efficient.
130 template <class Func>
131 auto via(Executor*, Func func)
132   -> Future<typename isFuture<decltype(func())>::Inner>;
133
134 /** When all the input Futures complete, the returned Future will complete.
135   Errors do not cause early termination; this Future will always succeed
136   after all its Futures have finished (whether successfully or with an
137   error).
138
139   The Futures are moved in, so your copies are invalid. If you need to
140   chain further from these Futures, use the variant with an output iterator.
141
142   This function is thread-safe for Futures running on different threads. But
143   if you are doing anything non-trivial after, you will probably want to
144   follow with `via(executor)` because it will complete in whichever thread the
145   last Future completes in.
146
147   The return type for Future<T> input is a Future<std::vector<Try<T>>>
148   */
149 template <class InputIterator>
150 Future<std::vector<Try<
151   typename std::iterator_traits<InputIterator>::value_type::value_type>>>
152 collectAll(InputIterator first, InputIterator last);
153
154 /// Sugar for the most common case
155 template <class Collection>
156 auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
157   return collectAll(c.begin(), c.end());
158 }
159
160 /// This version takes a varying number of Futures instead of an iterator.
161 /// The return type for (Future<T1>, Future<T2>, ...) input
162 /// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
163 /// The Futures are moved in, so your copies are invalid.
164 template <typename... Fs>
165 typename detail::CollectAllVariadicContext<
166   typename std::decay<Fs>::type::value_type...>::type
167 collectAll(Fs&&... fs);
168
169 /// Like collectAll, but will short circuit on the first exception. Thus, the
170 /// type of the returned Future is std::vector<T> instead of
171 /// std::vector<Try<T>>
172 template <class InputIterator>
173 Future<typename detail::CollectContext<
174   typename std::iterator_traits<InputIterator>::value_type::value_type
175 >::result_type>
176 collect(InputIterator first, InputIterator last);
177
178 /// Sugar for the most common case
179 template <class Collection>
180 auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
181   return collect(c.begin(), c.end());
182 }
183
184 /// Like collectAll, but will short circuit on the first exception. Thus, the
185 /// type of the returned Future is std::tuple<T1, T2, ...> instead of
186 /// std::tuple<Try<T1>, Try<T2>, ...>
187 template <typename... Fs>
188 typename detail::CollectVariadicContext<
189   typename std::decay<Fs>::type::value_type...>::type
190 collect(Fs&&... fs);
191
192 /** The result is a pair of the index of the first Future to complete and
193   the Try. If multiple Futures complete at the same time (or are already
194   complete when passed in), the "winner" is chosen non-deterministically.
195
196   This function is thread-safe for Futures running on different threads.
197   */
198 template <class InputIterator>
199 Future<std::pair<
200   size_t,
201   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
202 collectAny(InputIterator first, InputIterator last);
203
204 /// Sugar for the most common case
205 template <class Collection>
206 auto collectAny(Collection&& c) -> decltype(collectAny(c.begin(), c.end())) {
207   return collectAny(c.begin(), c.end());
208 }
209
210 /** when n Futures have completed, the Future completes with a vector of
211   the index and Try of those n Futures (the indices refer to the original
212   order, but the result vector will be in an arbitrary order)
213
214   Not thread safe.
215   */
216 template <class InputIterator>
217 Future<std::vector<std::pair<
218   size_t,
219   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
220 collectN(InputIterator first, InputIterator last, size_t n);
221
222 /// Sugar for the most common case
223 template <class Collection>
224 auto collectN(Collection&& c, size_t n)
225     -> decltype(collectN(c.begin(), c.end(), n)) {
226   return collectN(c.begin(), c.end(), n);
227 }
228
229 /** window creates up to n Futures using the values
230     in the collection, and then another Future for each Future
231     that completes
232
233     this is basically a sliding window of Futures of size n
234
235     func must return a Future for each value in input
236   */
237 template <class Collection, class F,
238           class ItT = typename std::iterator_traits<
239             typename Collection::iterator>::value_type,
240           class Result = typename detail::resultOf<F, ItT&&>::value_type>
241 std::vector<Future<Result>>
242 window(Collection input, F func, size_t n);
243
244 template <typename F, typename T, typename ItT>
245 using MaybeTryArg = typename std::conditional<
246   detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type;
247
248 template<typename F, typename T, typename Arg>
249 using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;
250
251 /** repeatedly calls func on every result, e.g.
252     reduce(reduce(reduce(T initial, result of first), result of second), ...)
253
254     The type of the final result is a Future of the type of the initial value.
255
256     Func can either return a T, or a Future<T>
257
258     func is called in order of the input, see unorderedReduce if that is not
259     a requirement
260   */
261 template <class It, class T, class F>
262 Future<T> reduce(It first, It last, T&& initial, F&& func);
263
264 /// Sugar for the most common case
265 template <class Collection, class T, class F>
266 auto reduce(Collection&& c, T&& initial, F&& func)
267     -> decltype(reduce(c.begin(), c.end(), std::forward<T>(initial),
268                 std::forward<F>(func))) {
269   return reduce(
270       c.begin(),
271       c.end(),
272       std::forward<T>(initial),
273       std::forward<F>(func));
274 }
275
276 /** like reduce, but calls func on finished futures as they complete
277     does NOT keep the order of the input
278   */
279 template <class It, class T, class F,
280           class ItT = typename std::iterator_traits<It>::value_type::value_type,
281           class Arg = MaybeTryArg<F, T, ItT>>
282 Future<T> unorderedReduce(It first, It last, T initial, F func);
283
284 /// Sugar for the most common case
285 template <class Collection, class T, class F>
286 auto unorderedReduce(Collection&& c, T&& initial, F&& func)
287     -> decltype(unorderedReduce(c.begin(), c.end(), std::forward<T>(initial),
288                 std::forward<F>(func))) {
289   return unorderedReduce(
290       c.begin(),
291       c.end(),
292       std::forward<T>(initial),
293       std::forward<F>(func));
294 }
295
296 } // namespace