a5198e714be908099a743c6b0da507e9fc146ae3
[folly.git] / folly / futures / helpers.h
1 /*
2  * Copyright 2017 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 <atomic>
19 #include <tuple>
20 #include <utility>
21
22 #include <folly/Portability.h>
23 #include <folly/Try.h>
24 #include <folly/futures/Future.h>
25 #include <folly/futures/Promise.h>
26
27 namespace folly {
28
29 namespace futures {
30 namespace detail {
31 template <typename... Ts>
32 struct CollectAllVariadicContext {
33   CollectAllVariadicContext() {}
34   template <typename T, size_t I>
35   inline void setPartialResult(Try<T>& t) {
36     std::get<I>(results) = std::move(t);
37   }
38   ~CollectAllVariadicContext() {
39     p.setValue(std::move(results));
40   }
41   Promise<std::tuple<Try<Ts>...>> p;
42   std::tuple<Try<Ts>...> results;
43   typedef Future<std::tuple<Try<Ts>...>> type;
44 };
45
46 template <typename... Ts>
47 struct CollectVariadicContext {
48   CollectVariadicContext() {}
49   template <typename T, size_t I>
50   inline void setPartialResult(Try<T>& t) {
51     if (t.hasException()) {
52       if (!threw.exchange(true)) {
53         p.setException(std::move(t.exception()));
54       }
55     } else if (!threw) {
56       std::get<I>(results) = std::move(t);
57     }
58   }
59   ~CollectVariadicContext() noexcept {
60     if (!threw.exchange(true)) {
61       p.setValue(unwrapTryTuple(std::move(results)));
62     }
63   }
64   Promise<std::tuple<Ts...>> p;
65   std::tuple<folly::Try<Ts>...> results;
66   std::atomic<bool> threw{false};
67   typedef Future<std::tuple<Ts...>> type;
68 };
69 } // namespace detail
70 } // namespace futures
71
72 /// This namespace is for utility functions that would usually be static
73 /// members of Future, except they don't make sense there because they don't
74 /// depend on the template type (rather, on the type of their arguments in
75 /// some cases). This is the least-bad naming scheme we could think of. Some
76 /// of the functions herein have really-likely-to-collide names, like "map"
77 /// and "sleep".
78 namespace futures {
79   /// Returns a Future that will complete after the specified duration. The
80   /// Duration typedef of a `std::chrono` duration type indicates the
81   /// resolution you can expect to be meaningful (milliseconds at the time of
82   /// writing). Normally you wouldn't need to specify a Timekeeper, we will
83   /// use the global futures timekeeper (we run a thread whose job it is to
84   /// keep time for futures timeouts) but we provide the option for power
85   /// users.
86   ///
87   /// The Timekeeper thread will be lazily created the first time it is
88   /// needed. If your program never uses any timeouts or other time-based
89   /// Futures you will pay no Timekeeper thread overhead.
90   Future<Unit> sleep(Duration, Timekeeper* = nullptr);
91
92   /**
93    * Set func as the callback for each input Future and return a vector of
94    * Futures containing the results in the input order.
95    */
96   template <
97       class It,
98       class F,
99       class ItT = typename std::iterator_traits<It>::value_type,
100       class Result = typename decltype(
101           std::declval<ItT>().then(std::declval<F>()))::value_type>
102   std::vector<Future<Result>> map(It first, It last, F func);
103
104   // Sugar for the most common case
105   template <class Collection, class F>
106   auto map(Collection&& c, F&& func)
107       -> decltype(map(c.begin(), c.end(), func)) {
108     return map(c.begin(), c.end(), std::forward<F>(func));
109   }
110
111 } // namespace futures
112
113 /**
114   Make a completed Future by moving in a value. e.g.
115
116     string foo = "foo";
117     auto f = makeFuture(std::move(foo));
118
119   or
120
121     auto f = makeFuture<string>("foo");
122 */
123 template <class T>
124 Future<typename std::decay<T>::type> makeFuture(T&& t);
125
126 /** Make a completed void Future. */
127 Future<Unit> makeFuture();
128
129 /**
130   Make a Future by executing a function.
131
132   If the function returns a value of type T, makeFutureWith
133   returns a completed Future<T>, capturing the value returned
134   by the function.
135
136   If the function returns a Future<T> already, makeFutureWith
137   returns just that.
138
139   Either way, if the function throws, a failed Future is
140   returned that captures the exception.
141
142   Calling makeFutureWith(func) is equivalent to calling
143   makeFuture().then(func).
144 */
145
146 // makeFutureWith(Future<T>()) -> Future<T>
147 template <class F>
148 typename std::enable_if<isFuture<typename std::result_of<F()>::type>::value,
149                         typename std::result_of<F()>::type>::type
150 makeFutureWith(F&& func);
151
152 // makeFutureWith(T()) -> Future<T>
153 // makeFutureWith(void()) -> Future<Unit>
154 template <class F>
155 typename std::enable_if<
156     !(isFuture<typename std::result_of<F()>::type>::value),
157     Future<typename Unit::Lift<typename std::result_of<F()>::type>::type>>::type
158 makeFutureWith(F&& func);
159
160 /// Make a failed Future from an exception_ptr.
161 /// Because the Future's type cannot be inferred you have to specify it, e.g.
162 ///
163 ///   auto f = makeFuture<string>(std::current_exception());
164 template <class T>
165 FOLLY_DEPRECATED("use makeFuture(exception_wrapper)")
166 Future<T> makeFuture(std::exception_ptr const& e);
167
168 /// Make a failed Future from an exception_wrapper.
169 template <class T>
170 Future<T> makeFuture(exception_wrapper ew);
171
172 /** Make a Future from an exception type E that can be passed to
173   std::make_exception_ptr(). */
174 template <class T, class E>
175 typename std::enable_if<std::is_base_of<std::exception, E>::value,
176                         Future<T>>::type
177 makeFuture(E const& e);
178
179 /** Make a Future out of a Try */
180 template <class T>
181 Future<T> makeFuture(Try<T>&& t);
182
183 /*
184  * Return a new Future that will call back on the given Executor.
185  * This is just syntactic sugar for makeFuture().via(executor)
186  *
187  * @param executor the Executor to call back on
188  * @param priority optionally, the priority to add with. Defaults to 0 which
189  * represents medium priority.
190  *
191  * @returns a void Future that will call back on the given executor
192  */
193 inline Future<Unit> via(
194     Executor* executor,
195     int8_t priority = Executor::MID_PRI);
196
197 /// Execute a function via the given executor and return a future.
198 /// This is semantically equivalent to via(executor).then(func), but
199 /// easier to read and slightly more efficient.
200 template <class Func>
201 auto via(Executor*, Func&& func)
202     -> Future<typename isFuture<decltype(std::declval<Func>()())>::Inner>;
203
204 /** When all the input Futures complete, the returned Future will complete.
205   Errors do not cause early termination; this Future will always succeed
206   after all its Futures have finished (whether successfully or with an
207   error).
208
209   The Futures are moved in, so your copies are invalid. If you need to
210   chain further from these Futures, use the variant with an output iterator.
211
212   This function is thread-safe for Futures running on different threads. But
213   if you are doing anything non-trivial after, you will probably want to
214   follow with `via(executor)` because it will complete in whichever thread the
215   last Future completes in.
216
217   The return type for Future<T> input is a Future<std::vector<Try<T>>>
218   */
219 template <class InputIterator>
220 Future<std::vector<Try<
221   typename std::iterator_traits<InputIterator>::value_type::value_type>>>
222 collectAll(InputIterator first, InputIterator last);
223
224 /// Sugar for the most common case
225 template <class Collection>
226 auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
227   return collectAll(c.begin(), c.end());
228 }
229
230 /// This version takes a varying number of Futures instead of an iterator.
231 /// The return type for (Future<T1>, Future<T2>, ...) input
232 /// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
233 /// The Futures are moved in, so your copies are invalid.
234 template <typename... Fs>
235 typename futures::detail::CollectAllVariadicContext<
236     typename std::decay<Fs>::type::value_type...>::type
237 collectAll(Fs&&... fs);
238
239 /// Like collectAll, but will short circuit on the first exception. Thus, the
240 /// type of the returned Future is std::vector<T> instead of
241 /// std::vector<Try<T>>
242 template <class InputIterator>
243 Future<typename futures::detail::CollectContext<typename std::iterator_traits<
244     InputIterator>::value_type::value_type>::result_type>
245 collect(InputIterator first, InputIterator last);
246
247 /// Sugar for the most common case
248 template <class Collection>
249 auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
250   return collect(c.begin(), c.end());
251 }
252
253 /// Like collectAll, but will short circuit on the first exception. Thus, the
254 /// type of the returned Future is std::tuple<T1, T2, ...> instead of
255 /// std::tuple<Try<T1>, Try<T2>, ...>
256 template <typename... Fs>
257 typename futures::detail::CollectVariadicContext<
258     typename std::decay<Fs>::type::value_type...>::type
259 collect(Fs&&... fs);
260
261 /** The result is a pair of the index of the first Future to complete and
262   the Try. If multiple Futures complete at the same time (or are already
263   complete when passed in), the "winner" is chosen non-deterministically.
264
265   This function is thread-safe for Futures running on different threads.
266   */
267 template <class InputIterator>
268 Future<std::pair<
269   size_t,
270   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
271 collectAny(InputIterator first, InputIterator last);
272
273 /// Sugar for the most common case
274 template <class Collection>
275 auto collectAny(Collection&& c) -> decltype(collectAny(c.begin(), c.end())) {
276   return collectAny(c.begin(), c.end());
277 }
278
279 /** Similar to collectAny, collectAnyWithoutException return the first Future to
280  * complete without exceptions. If none of the future complete without
281  * excpetions, the last exception will be returned as a result.
282   */
283 template <class InputIterator>
284 Future<std::pair<
285     size_t,
286     typename std::iterator_traits<InputIterator>::value_type::value_type>>
287 collectAnyWithoutException(InputIterator first, InputIterator last);
288
289 /// Sugar for the most common case
290 template <class Collection>
291 auto collectAnyWithoutException(Collection&& c)
292     -> decltype(collectAnyWithoutException(c.begin(), c.end())) {
293   return collectAnyWithoutException(c.begin(), c.end());
294 }
295
296 /** when n Futures have completed, the Future completes with a vector of
297   the index and Try of those n Futures (the indices refer to the original
298   order, but the result vector will be in an arbitrary order)
299
300   Not thread safe.
301   */
302 template <class InputIterator>
303 Future<std::vector<std::pair<
304   size_t,
305   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
306 collectN(InputIterator first, InputIterator last, size_t n);
307
308 /// Sugar for the most common case
309 template <class Collection>
310 auto collectN(Collection&& c, size_t n)
311     -> decltype(collectN(c.begin(), c.end(), n)) {
312   return collectN(c.begin(), c.end(), n);
313 }
314
315 /** window creates up to n Futures using the values
316     in the collection, and then another Future for each Future
317     that completes
318
319     this is basically a sliding window of Futures of size n
320
321     func must return a Future for each value in input
322   */
323 template <
324     class Collection,
325     class F,
326     class ItT = typename std::iterator_traits<
327         typename Collection::iterator>::value_type,
328     class Result = typename futures::detail::resultOf<F, ItT&&>::value_type>
329 std::vector<Future<Result>> window(Collection input, F func, size_t n);
330
331 template <
332     class Collection,
333     class F,
334     class ItT = typename std::iterator_traits<
335         typename Collection::iterator>::value_type,
336     class Result = typename futures::detail::resultOf<F, ItT&&>::value_type>
337 std::vector<Future<Result>>
338 window(Executor* executor, Collection input, F func, size_t n);
339
340 template <typename F, typename T, typename ItT>
341 using MaybeTryArg = typename std::conditional<
342     futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
343     Try<ItT>,
344     ItT>::type;
345
346 template <typename F, typename T, typename Arg>
347 using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;
348
349 /** repeatedly calls func on every result, e.g.
350     reduce(reduce(reduce(T initial, result of first), result of second), ...)
351
352     The type of the final result is a Future of the type of the initial value.
353
354     Func can either return a T, or a Future<T>
355
356     func is called in order of the input, see unorderedReduce if that is not
357     a requirement
358   */
359 template <class It, class T, class F>
360 Future<T> reduce(It first, It last, T&& initial, F&& func);
361
362 /// Sugar for the most common case
363 template <class Collection, class T, class F>
364 auto reduce(Collection&& c, T&& initial, F&& func)
365     -> decltype(reduce(c.begin(), c.end(), std::forward<T>(initial),
366                 std::forward<F>(func))) {
367   return reduce(
368       c.begin(),
369       c.end(),
370       std::forward<T>(initial),
371       std::forward<F>(func));
372 }
373
374 /** like reduce, but calls func on finished futures as they complete
375     does NOT keep the order of the input
376   */
377 template <
378     class It,
379     class T,
380     class F,
381     class ItT = typename std::iterator_traits<It>::value_type::value_type,
382     class Arg = MaybeTryArg<F, T, ItT>>
383 Future<T> unorderedReduce(It first, It last, T initial, F func);
384
385 /// Sugar for the most common case
386 template <class Collection, class T, class F>
387 auto unorderedReduce(Collection&& c, T&& initial, F&& func)
388     -> decltype(unorderedReduce(c.begin(), c.end(), std::forward<T>(initial),
389                 std::forward<F>(func))) {
390   return unorderedReduce(
391       c.begin(),
392       c.end(),
393       std::forward<T>(initial),
394       std::forward<F>(func));
395 }
396 } // namespace folly