Workaround MSVC bug with referencing template constructors before definition
[folly.git] / folly / futures / Future-inl.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
17 #pragma once
18
19 #include <algorithm>
20 #include <cassert>
21 #include <chrono>
22 #include <thread>
23
24 #include <folly/Baton.h>
25 #include <folly/Optional.h>
26 #include <folly/futures/Timekeeper.h>
27 #include <folly/futures/detail/Core.h>
28
29 #ifndef FOLLY_FUTURE_USING_FIBER
30 #if FOLLY_MOBILE || defined(__APPLE__)
31 #define FOLLY_FUTURE_USING_FIBER 0
32 #else
33 #define FOLLY_FUTURE_USING_FIBER 1
34 #include <folly/fibers/Baton.h>
35 #endif
36 #endif
37
38 namespace folly {
39
40 class Timekeeper;
41
42 namespace futures {
43 namespace detail {
44 #if FOLLY_FUTURE_USING_FIBER
45 typedef folly::fibers::Baton FutureBatonType;
46 #else
47 typedef folly::Baton<> FutureBatonType;
48 #endif
49 } // namespace detail
50 } // namespace futures
51
52 namespace detail {
53 std::shared_ptr<Timekeeper> getTimekeeperSingleton();
54 } // namespace detail
55
56 namespace futures {
57 namespace detail {
58 //  Guarantees that the stored functor is destructed before the stored promise
59 //  may be fulfilled. Assumes the stored functor to be noexcept-destructible.
60 template <typename T, typename F>
61 class CoreCallbackState {
62  public:
63   template <typename FF>
64   CoreCallbackState(Promise<T>&& promise, FF&& func) noexcept(
65       noexcept(F(std::declval<FF>())))
66       : func_(std::forward<FF>(func)), promise_(std::move(promise)) {
67     assert(before_barrier());
68   }
69
70   CoreCallbackState(CoreCallbackState&& that) noexcept(
71       noexcept(F(std::declval<F>()))) {
72     if (that.before_barrier()) {
73       new (&func_) F(std::move(that.func_));
74       promise_ = that.stealPromise();
75     }
76   }
77
78   CoreCallbackState& operator=(CoreCallbackState&&) = delete;
79
80   ~CoreCallbackState() {
81     if (before_barrier()) {
82       stealPromise();
83     }
84   }
85
86   template <typename... Args>
87   auto invoke(Args&&... args) noexcept(
88       noexcept(std::declval<F&&>()(std::declval<Args&&>()...))) {
89     assert(before_barrier());
90     return std::move(func_)(std::forward<Args>(args)...);
91   }
92
93   template <typename... Args>
94   auto tryInvoke(Args&&... args) noexcept {
95     return makeTryWith([&] { return invoke(std::forward<Args>(args)...); });
96   }
97
98   void setTry(Try<T>&& t) {
99     stealPromise().setTry(std::move(t));
100   }
101
102   void setException(exception_wrapper&& ew) {
103     stealPromise().setException(std::move(ew));
104   }
105
106   Promise<T> stealPromise() noexcept {
107     assert(before_barrier());
108     func_.~F();
109     return std::move(promise_);
110   }
111
112  private:
113   bool before_barrier() const noexcept {
114     return !promise_.isFulfilled();
115   }
116
117   union {
118     F func_;
119   };
120   Promise<T> promise_{Promise<T>::makeEmpty()};
121 };
122
123 template <typename T, typename F>
124 inline auto makeCoreCallbackState(Promise<T>&& p, F&& f) noexcept(
125     noexcept(CoreCallbackState<T, _t<std::decay<F>>>(
126         std::declval<Promise<T>&&>(),
127         std::declval<F&&>()))) {
128   return CoreCallbackState<T, _t<std::decay<F>>>(
129       std::move(p), std::forward<F>(f));
130 }
131 } // namespace detail
132 } // namespace futures
133
134 template <class T>
135 SemiFuture<typename std::decay<T>::type> makeSemiFuture(T&& t) {
136   return makeSemiFuture(Try<typename std::decay<T>::type>(std::forward<T>(t)));
137 }
138
139 // makeSemiFutureWith(SemiFuture<T>()) -> SemiFuture<T>
140 template <class F>
141 typename std::enable_if<
142     isSemiFuture<typename std::result_of<F()>::type>::value,
143     typename std::result_of<F()>::type>::type
144 makeSemiFutureWith(F&& func) {
145   using InnerType =
146       typename isSemiFuture<typename std::result_of<F()>::type>::Inner;
147   try {
148     return std::forward<F>(func)();
149   } catch (std::exception& e) {
150     return makeSemiFuture<InnerType>(
151         exception_wrapper(std::current_exception(), e));
152   } catch (...) {
153     return makeSemiFuture<InnerType>(
154         exception_wrapper(std::current_exception()));
155   }
156 }
157
158 // makeSemiFutureWith(T()) -> SemiFuture<T>
159 // makeSemiFutureWith(void()) -> SemiFuture<Unit>
160 template <class F>
161 typename std::enable_if<
162     !(isSemiFuture<typename std::result_of<F()>::type>::value),
163     SemiFuture<Unit::LiftT<typename std::result_of<F()>::type>>>::type
164 makeSemiFutureWith(F&& func) {
165   using LiftedResult = Unit::LiftT<typename std::result_of<F()>::type>;
166   return makeSemiFuture<LiftedResult>(
167       makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
168 }
169
170 template <class T>
171 SemiFuture<T> makeSemiFuture(std::exception_ptr const& e) {
172   return makeSemiFuture(Try<T>(e));
173 }
174
175 template <class T>
176 SemiFuture<T> makeSemiFuture(exception_wrapper ew) {
177   return makeSemiFuture(Try<T>(std::move(ew)));
178 }
179
180 template <class T, class E>
181 typename std::
182     enable_if<std::is_base_of<std::exception, E>::value, SemiFuture<T>>::type
183     makeSemiFuture(E const& e) {
184   return makeSemiFuture(Try<T>(make_exception_wrapper<E>(e)));
185 }
186
187 template <class T>
188 SemiFuture<T> makeSemiFuture(Try<T>&& t) {
189   return SemiFuture<T>(new futures::detail::Core<T>(std::move(t)));
190 }
191
192 template <class T>
193 SemiFuture<T> SemiFuture<T>::makeEmpty() {
194   return SemiFuture<T>(futures::detail::EmptyConstruct{});
195 }
196
197 template <class T>
198 SemiFuture<T>::SemiFuture(SemiFuture<T>&& other) noexcept : core_(other.core_) {
199   other.core_ = nullptr;
200 }
201
202 template <class T>
203 SemiFuture<T>& SemiFuture<T>::operator=(SemiFuture<T>&& other) noexcept {
204   std::swap(core_, other.core_);
205   return *this;
206 }
207
208 template <class T>
209 SemiFuture<T>::SemiFuture(Future<T>&& other) noexcept : core_(other.core_) {
210   other.core_ = nullptr;
211 }
212
213 template <class T>
214 SemiFuture<T>& SemiFuture<T>::operator=(Future<T>&& other) noexcept {
215   std::swap(core_, other.core_);
216   return *this;
217 }
218
219 template <class T>
220 template <class T2, typename>
221 SemiFuture<T>::SemiFuture(T2&& val)
222     : core_(new futures::detail::Core<T>(Try<T>(std::forward<T2>(val)))) {}
223
224 template <class T>
225 template <typename T2>
226 SemiFuture<T>::SemiFuture(
227     typename std::enable_if<std::is_same<Unit, T2>::value>::type*)
228     : core_(new futures::detail::Core<T>(Try<T>(T()))) {}
229
230 template <class T>
231 template <
232     class... Args,
233     typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
234         type>
235 SemiFuture<T>::SemiFuture(in_place_t, Args&&... args)
236     : core_(
237           new futures::detail::Core<T>(in_place, std::forward<Args>(args)...)) {
238 }
239
240 template <class T>
241 SemiFuture<T>::~SemiFuture() {
242   detach();
243 }
244
245 // This must be defined after the constructors to avoid a bug in MSVC
246 // https://connect.microsoft.com/VisualStudio/feedback/details/3142777/out-of-line-constructor-definition-after-implicit-reference-causes-incorrect-c2244
247 inline SemiFuture<Unit> makeSemiFuture() {
248   return makeSemiFuture(Unit{});
249 }
250
251 template <class T>
252 T& SemiFuture<T>::value() & {
253   throwIfInvalid();
254
255   return core_->getTry().value();
256 }
257
258 template <class T>
259 T const& SemiFuture<T>::value() const& {
260   throwIfInvalid();
261
262   return core_->getTry().value();
263 }
264
265 template <class T>
266 T&& SemiFuture<T>::value() && {
267   throwIfInvalid();
268
269   return std::move(core_->getTry().value());
270 }
271
272 template <class T>
273 T const&& SemiFuture<T>::value() const&& {
274   throwIfInvalid();
275
276   return std::move(core_->getTry().value());
277 }
278
279 template <class T>
280 inline Future<T> SemiFuture<T>::via(Executor* executor, int8_t priority) && {
281   throwIfInvalid();
282
283   setExecutor(executor, priority);
284
285   auto newFuture = Future<T>(core_);
286   core_ = nullptr;
287   return newFuture;
288 }
289
290 template <class T>
291 inline Future<T> SemiFuture<T>::via(Executor* executor, int8_t priority) & {
292   throwIfInvalid();
293   Promise<T> p;
294   auto f = p.getFuture();
295   auto func = [p = std::move(p)](Try<T>&& t) mutable {
296     p.setTry(std::move(t));
297   };
298   using R = futures::detail::callableResult<T, decltype(func)>;
299   thenImplementation<decltype(func), R>(std::move(func), typename R::Arg());
300   return std::move(f).via(executor, priority);
301 }
302
303 template <class T>
304 bool SemiFuture<T>::isReady() const {
305   throwIfInvalid();
306   return core_->ready();
307 }
308
309 template <class T>
310 bool SemiFuture<T>::hasValue() {
311   return getTry().hasValue();
312 }
313
314 template <class T>
315 bool SemiFuture<T>::hasException() {
316   return getTry().hasException();
317 }
318
319 template <class T>
320 void SemiFuture<T>::detach() {
321   if (core_) {
322     core_->detachFuture();
323     core_ = nullptr;
324   }
325 }
326
327 template <class T>
328 Try<T>& SemiFuture<T>::getTry() {
329   throwIfInvalid();
330
331   return core_->getTry();
332 }
333
334 template <class T>
335 void SemiFuture<T>::throwIfInvalid() const {
336   if (!core_)
337     throwNoState();
338 }
339
340 template <class T>
341 Optional<Try<T>> SemiFuture<T>::poll() {
342   Optional<Try<T>> o;
343   if (core_->ready()) {
344     o = std::move(core_->getTry());
345   }
346   return o;
347 }
348
349 template <class T>
350 void SemiFuture<T>::raise(exception_wrapper exception) {
351   core_->raise(std::move(exception));
352 }
353
354 template <class T>
355 template <class F>
356 void SemiFuture<T>::setCallback_(F&& func) {
357   throwIfInvalid();
358   core_->setCallback(std::forward<F>(func));
359 }
360
361 template <class T>
362 SemiFuture<T>::SemiFuture(futures::detail::EmptyConstruct) noexcept
363     : core_(nullptr) {}
364
365 template <class T>
366 Future<T> Future<T>::makeEmpty() {
367   return Future<T>(futures::detail::EmptyConstruct{});
368 }
369
370 template <class T>
371 Future<T>::Future(Future<T>&& other) noexcept
372     : SemiFuture<T>(std::move(other)) {}
373
374 template <class T>
375 Future<T>& Future<T>::operator=(Future<T>&& other) noexcept {
376   SemiFuture<T>::operator=(SemiFuture<T>{std::move(other)});
377   return *this;
378 }
379
380 template <class T>
381 template <
382     class T2,
383     typename std::enable_if<
384         !std::is_same<T, typename std::decay<T2>::type>::value &&
385             std::is_constructible<T, T2&&>::value &&
386             std::is_convertible<T2&&, T>::value,
387         int>::type>
388 Future<T>::Future(Future<T2>&& other)
389     : Future(std::move(other).then([](T2&& v) { return T(std::move(v)); })) {}
390
391 template <class T>
392 template <
393     class T2,
394     typename std::enable_if<
395         !std::is_same<T, typename std::decay<T2>::type>::value &&
396             std::is_constructible<T, T2&&>::value &&
397             !std::is_convertible<T2&&, T>::value,
398         int>::type>
399 Future<T>::Future(Future<T2>&& other)
400     : Future(std::move(other).then([](T2&& v) { return T(std::move(v)); })) {}
401
402 template <class T>
403 template <
404     class T2,
405     typename std::enable_if<
406         !std::is_same<T, typename std::decay<T2>::type>::value &&
407             std::is_constructible<T, T2&&>::value,
408         int>::type>
409 Future<T>& Future<T>::operator=(Future<T2>&& other) {
410   return operator=(
411       std::move(other).then([](T2&& v) { return T(std::move(v)); }));
412 }
413
414 // TODO: isSemiFuture
415 template <class T>
416 template <class T2, typename>
417 Future<T>::Future(T2&& val) : SemiFuture<T>(std::forward<T2>(val)) {}
418
419 template <class T>
420 template <typename T2>
421 Future<T>::Future(typename std::enable_if<std::is_same<Unit, T2>::value>::type*)
422     : SemiFuture<T>() {}
423
424 template <class T>
425 template <
426     class... Args,
427     typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
428         type>
429 Future<T>::Future(in_place_t, Args&&... args)
430     : SemiFuture<T>(in_place, std::forward<Args>(args)...) {}
431
432 template <class T>
433 Future<T>::~Future() {
434 }
435
436 // unwrap
437
438 template <class T>
439 template <class F>
440 typename std::enable_if<isFuture<F>::value,
441                         Future<typename isFuture<T>::Inner>>::type
442 Future<T>::unwrap() {
443   return then([](Future<typename isFuture<T>::Inner> internal_future) {
444       return internal_future;
445   });
446 }
447
448 // then
449
450 // Variant: returns a value
451 // e.g. f.then([](Try<T>&& t){ return t.value(); });
452 template <class T>
453 template <typename F, typename R, bool isTry, typename... Args>
454 typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
455 SemiFuture<T>::thenImplementation(
456     F&& func,
457     futures::detail::argResult<isTry, F, Args...>) {
458   static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
459   typedef typename R::ReturnsFuture::Inner B;
460
461   this->throwIfInvalid();
462
463   Promise<B> p;
464   p.core_->setInterruptHandlerNoLock(this->core_->getInterruptHandler());
465
466   // grab the Future now before we lose our handle on the Promise
467   auto f = p.getFuture();
468   f.core_->setExecutorNoLock(this->getExecutor());
469
470   /* This is a bit tricky.
471
472      We can't just close over *this in case this Future gets moved. So we
473      make a new dummy Future. We could figure out something more
474      sophisticated that avoids making a new Future object when it can, as an
475      optimization. But this is correct.
476
477      core_ can't be moved, it is explicitly disallowed (as is copying). But
478      if there's ever a reason to allow it, this is one place that makes that
479      assumption and would need to be fixed. We use a standard shared pointer
480      for core_ (by copying it in), which means in essence obj holds a shared
481      pointer to itself.  But this shouldn't leak because Promise will not
482      outlive the continuation, because Promise will setException() with a
483      broken Promise if it is destructed before completed. We could use a
484      weak pointer but it would have to be converted to a shared pointer when
485      func is executed (because the Future returned by func may possibly
486      persist beyond the callback, if it gets moved), and so it is an
487      optimization to just make it shared from the get-go.
488
489      Two subtle but important points about this design. futures::detail::Core
490      has no back pointers to Future or Promise, so if Future or Promise get
491      moved (and they will be moved in performant code) we don't have to do
492      anything fancy. And because we store the continuation in the
493      futures::detail::Core, not in the Future, we can execute the continuation
494      even after the Future has gone out of scope. This is an intentional design
495      decision. It is likely we will want to be able to cancel a continuation
496      in some circumstances, but I think it should be explicit not implicit
497      in the destruction of the Future used to create it.
498      */
499   this->setCallback_(
500       [state = futures::detail::makeCoreCallbackState(
501            std::move(p), std::forward<F>(func))](Try<T>&& t) mutable {
502
503         if (!isTry && t.hasException()) {
504           state.setException(std::move(t.exception()));
505         } else {
506           state.setTry(makeTryWith(
507               [&] { return state.invoke(t.template get<isTry, Args>()...); }));
508         }
509       });
510   return f;
511 }
512
513 // Variant: returns a Future
514 // e.g. f.then([](T&& t){ return makeFuture<T>(t); });
515 template <class T>
516 template <typename F, typename R, bool isTry, typename... Args>
517 typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
518 SemiFuture<T>::thenImplementation(
519     F&& func,
520     futures::detail::argResult<isTry, F, Args...>) {
521   static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
522   typedef typename R::ReturnsFuture::Inner B;
523   this->throwIfInvalid();
524
525   Promise<B> p;
526   p.core_->setInterruptHandlerNoLock(this->core_->getInterruptHandler());
527
528   // grab the Future now before we lose our handle on the Promise
529   auto f = p.getFuture();
530   f.core_->setExecutorNoLock(this->getExecutor());
531
532   this->setCallback_(
533       [state = futures::detail::makeCoreCallbackState(
534            std::move(p), std::forward<F>(func))](Try<T>&& t) mutable {
535         if (!isTry && t.hasException()) {
536           state.setException(std::move(t.exception()));
537         } else {
538           auto tf2 = state.tryInvoke(t.template get<isTry, Args>()...);
539           if (tf2.hasException()) {
540             state.setException(std::move(tf2.exception()));
541           } else {
542             tf2->setCallback_([p = state.stealPromise()](Try<B> && b) mutable {
543               p.setTry(std::move(b));
544             });
545           }
546         }
547       });
548
549   return f;
550 }
551
552 template <typename T>
553 template <typename R, typename Caller, typename... Args>
554   Future<typename isFuture<R>::Inner>
555 Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
556   typedef typename std::remove_cv<typename std::remove_reference<
557       typename futures::detail::ArgType<Args...>::FirstArg>::type>::type
558       FirstArg;
559
560   return then([instance, func](Try<T>&& t){
561     return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
562   });
563 }
564
565 template <class T>
566 Future<Unit> Future<T>::then() {
567   return then([] () {});
568 }
569
570 // onError where the callback returns T
571 template <class T>
572 template <class F>
573 typename std::enable_if<
574     !futures::detail::callableWith<F, exception_wrapper>::value &&
575         !futures::detail::callableWith<F, exception_wrapper&>::value &&
576         !futures::detail::Extract<F>::ReturnsFuture::value,
577     Future<T>>::type
578 Future<T>::onError(F&& func) {
579   typedef std::remove_reference_t<
580       typename futures::detail::Extract<F>::FirstArg>
581       Exn;
582   static_assert(
583       std::is_same<typename futures::detail::Extract<F>::RawReturn, T>::value,
584       "Return type of onError callback must be T or Future<T>");
585
586   Promise<T> p;
587   p.core_->setInterruptHandlerNoLock(this->core_->getInterruptHandler());
588   auto f = p.getFuture();
589
590   this->setCallback_(
591       [state = futures::detail::makeCoreCallbackState(
592            std::move(p), std::forward<F>(func))](Try<T>&& t) mutable {
593         if (auto e = t.template tryGetExceptionObject<Exn>()) {
594           state.setTry(makeTryWith([&] { return state.invoke(*e); }));
595         } else {
596           state.setTry(std::move(t));
597         }
598       });
599
600   return f;
601 }
602
603 // onError where the callback returns Future<T>
604 template <class T>
605 template <class F>
606 typename std::enable_if<
607     !futures::detail::callableWith<F, exception_wrapper>::value &&
608         !futures::detail::callableWith<F, exception_wrapper&>::value &&
609         futures::detail::Extract<F>::ReturnsFuture::value,
610     Future<T>>::type
611 Future<T>::onError(F&& func) {
612   static_assert(
613       std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
614           value,
615       "Return type of onError callback must be T or Future<T>");
616   typedef std::remove_reference_t<
617       typename futures::detail::Extract<F>::FirstArg>
618       Exn;
619
620   Promise<T> p;
621   auto f = p.getFuture();
622
623   this->setCallback_(
624       [state = futures::detail::makeCoreCallbackState(
625            std::move(p), std::forward<F>(func))](Try<T>&& t) mutable {
626         if (auto e = t.template tryGetExceptionObject<Exn>()) {
627           auto tf2 = state.tryInvoke(*e);
628           if (tf2.hasException()) {
629             state.setException(std::move(tf2.exception()));
630           } else {
631             tf2->setCallback_([p = state.stealPromise()](Try<T> && t3) mutable {
632               p.setTry(std::move(t3));
633             });
634           }
635         } else {
636           state.setTry(std::move(t));
637         }
638       });
639
640   return f;
641 }
642
643 template <class T>
644 template <class F>
645 Future<T> Future<T>::ensure(F&& func) {
646   return this->then([funcw = std::forward<F>(func)](Try<T> && t) mutable {
647     std::move(funcw)();
648     return makeFuture(std::move(t));
649   });
650 }
651
652 template <class T>
653 template <class F>
654 Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
655   return within(dur, tk).onError([funcw = std::forward<F>(func)](
656       TimedOut const&) { return std::move(funcw)(); });
657 }
658
659 template <class T>
660 template <class F>
661 typename std::enable_if<
662     futures::detail::callableWith<F, exception_wrapper>::value &&
663         futures::detail::Extract<F>::ReturnsFuture::value,
664     Future<T>>::type
665 Future<T>::onError(F&& func) {
666   static_assert(
667       std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
668           value,
669       "Return type of onError callback must be T or Future<T>");
670
671   Promise<T> p;
672   auto f = p.getFuture();
673   this->setCallback_(
674       [state = futures::detail::makeCoreCallbackState(
675            std::move(p), std::forward<F>(func))](Try<T> t) mutable {
676         if (t.hasException()) {
677           auto tf2 = state.tryInvoke(std::move(t.exception()));
678           if (tf2.hasException()) {
679             state.setException(std::move(tf2.exception()));
680           } else {
681             tf2->setCallback_([p = state.stealPromise()](Try<T> && t3) mutable {
682               p.setTry(std::move(t3));
683             });
684           }
685         } else {
686           state.setTry(std::move(t));
687         }
688       });
689
690   return f;
691 }
692
693 // onError(exception_wrapper) that returns T
694 template <class T>
695 template <class F>
696 typename std::enable_if<
697     futures::detail::callableWith<F, exception_wrapper>::value &&
698         !futures::detail::Extract<F>::ReturnsFuture::value,
699     Future<T>>::type
700 Future<T>::onError(F&& func) {
701   static_assert(
702       std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
703           value,
704       "Return type of onError callback must be T or Future<T>");
705
706   Promise<T> p;
707   auto f = p.getFuture();
708   this->setCallback_(
709       [state = futures::detail::makeCoreCallbackState(
710            std::move(p), std::forward<F>(func))](Try<T>&& t) mutable {
711         if (t.hasException()) {
712           state.setTry(makeTryWith(
713               [&] { return state.invoke(std::move(t.exception())); }));
714         } else {
715           state.setTry(std::move(t));
716         }
717       });
718
719   return f;
720 }
721
722 template <class T>
723 Try<T>& Future<T>::getTryVia(DrivableExecutor* e) {
724   return waitVia(e).getTry();
725 }
726
727 template <class Func>
728 auto via(Executor* x, Func&& func)
729     -> Future<typename isFuture<decltype(std::declval<Func>()())>::Inner> {
730   // TODO make this actually more performant. :-P #7260175
731   return via(x).then(std::forward<Func>(func));
732 }
733
734 template <class T>
735 Future<T>::Future(futures::detail::EmptyConstruct) noexcept
736     : SemiFuture<T>(futures::detail::EmptyConstruct{}) {}
737
738 // makeFuture
739
740 template <class T>
741 Future<typename std::decay<T>::type> makeFuture(T&& t) {
742   return makeFuture(Try<typename std::decay<T>::type>(std::forward<T>(t)));
743 }
744
745 inline Future<Unit> makeFuture() {
746   return makeFuture(Unit{});
747 }
748
749 // makeFutureWith(Future<T>()) -> Future<T>
750 template <class F>
751 typename std::enable_if<isFuture<typename std::result_of<F()>::type>::value,
752                         typename std::result_of<F()>::type>::type
753 makeFutureWith(F&& func) {
754   using InnerType =
755       typename isFuture<typename std::result_of<F()>::type>::Inner;
756   try {
757     return std::forward<F>(func)();
758   } catch (std::exception& e) {
759     return makeFuture<InnerType>(
760         exception_wrapper(std::current_exception(), e));
761   } catch (...) {
762     return makeFuture<InnerType>(exception_wrapper(std::current_exception()));
763   }
764 }
765
766 // makeFutureWith(T()) -> Future<T>
767 // makeFutureWith(void()) -> Future<Unit>
768 template <class F>
769 typename std::enable_if<
770     !(isFuture<typename std::result_of<F()>::type>::value),
771     Future<Unit::LiftT<typename std::result_of<F()>::type>>>::type
772 makeFutureWith(F&& func) {
773   using LiftedResult = Unit::LiftT<typename std::result_of<F()>::type>;
774   return makeFuture<LiftedResult>(
775       makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
776 }
777
778 template <class T>
779 Future<T> makeFuture(std::exception_ptr const& e) {
780   return makeFuture(Try<T>(e));
781 }
782
783 template <class T>
784 Future<T> makeFuture(exception_wrapper ew) {
785   return makeFuture(Try<T>(std::move(ew)));
786 }
787
788 template <class T, class E>
789 typename std::enable_if<std::is_base_of<std::exception, E>::value,
790                         Future<T>>::type
791 makeFuture(E const& e) {
792   return makeFuture(Try<T>(make_exception_wrapper<E>(e)));
793 }
794
795 template <class T>
796 Future<T> makeFuture(Try<T>&& t) {
797   return Future<T>(new futures::detail::Core<T>(std::move(t)));
798 }
799
800 // via
801 Future<Unit> via(Executor* executor, int8_t priority) {
802   return makeFuture().via(executor, priority);
803 }
804
805 // mapSetCallback calls func(i, Try<T>) when every future completes
806
807 template <class T, class InputIterator, class F>
808 void mapSetCallback(InputIterator first, InputIterator last, F func) {
809   for (size_t i = 0; first != last; ++first, ++i) {
810     first->setCallback_([func, i](Try<T>&& t) {
811       func(i, std::move(t));
812     });
813   }
814 }
815
816 // collectAll (variadic)
817
818 template <typename... Fs>
819 typename futures::detail::CollectAllVariadicContext<
820     typename std::decay<Fs>::type::value_type...>::type
821 collectAll(Fs&&... fs) {
822   auto ctx = std::make_shared<futures::detail::CollectAllVariadicContext<
823       typename std::decay<Fs>::type::value_type...>>();
824   futures::detail::collectVariadicHelper<
825       futures::detail::CollectAllVariadicContext>(ctx, std::forward<Fs>(fs)...);
826   return ctx->p.getFuture();
827 }
828
829 // collectAll (iterator)
830
831 template <class InputIterator>
832 Future<
833   std::vector<
834   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
835 collectAll(InputIterator first, InputIterator last) {
836   typedef
837     typename std::iterator_traits<InputIterator>::value_type::value_type T;
838
839   struct CollectAllContext {
840     CollectAllContext(size_t n) : results(n) {}
841     ~CollectAllContext() {
842       p.setValue(std::move(results));
843     }
844     Promise<std::vector<Try<T>>> p;
845     std::vector<Try<T>> results;
846   };
847
848   auto ctx =
849       std::make_shared<CollectAllContext>(size_t(std::distance(first, last)));
850   mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
851     ctx->results[i] = std::move(t);
852   });
853   return ctx->p.getFuture();
854 }
855
856 // collect (iterator)
857
858 namespace futures {
859 namespace detail {
860
861 template <typename T>
862 struct CollectContext {
863   struct Nothing {
864     explicit Nothing(int /* n */) {}
865   };
866
867   using Result = typename std::conditional<
868     std::is_void<T>::value,
869     void,
870     std::vector<T>>::type;
871
872   using InternalResult = typename std::conditional<
873     std::is_void<T>::value,
874     Nothing,
875     std::vector<Optional<T>>>::type;
876
877   explicit CollectContext(size_t n) : result(n) {}
878   ~CollectContext() {
879     if (!threw.exchange(true)) {
880       // map Optional<T> -> T
881       std::vector<T> finalResult;
882       finalResult.reserve(result.size());
883       std::transform(result.begin(), result.end(),
884                      std::back_inserter(finalResult),
885                      [](Optional<T>& o) { return std::move(o.value()); });
886       p.setValue(std::move(finalResult));
887     }
888   }
889   inline void setPartialResult(size_t i, Try<T>& t) {
890     result[i] = std::move(t.value());
891   }
892   Promise<Result> p;
893   InternalResult result;
894   std::atomic<bool> threw {false};
895 };
896
897 } // namespace detail
898 } // namespace futures
899
900 template <class InputIterator>
901 Future<typename futures::detail::CollectContext<typename std::iterator_traits<
902     InputIterator>::value_type::value_type>::Result>
903 collect(InputIterator first, InputIterator last) {
904   typedef
905     typename std::iterator_traits<InputIterator>::value_type::value_type T;
906
907   auto ctx = std::make_shared<futures::detail::CollectContext<T>>(
908       std::distance(first, last));
909   mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
910     if (t.hasException()) {
911        if (!ctx->threw.exchange(true)) {
912          ctx->p.setException(std::move(t.exception()));
913        }
914      } else if (!ctx->threw) {
915        ctx->setPartialResult(i, t);
916      }
917   });
918   return ctx->p.getFuture();
919 }
920
921 // collect (variadic)
922
923 template <typename... Fs>
924 typename futures::detail::CollectVariadicContext<
925     typename std::decay<Fs>::type::value_type...>::type
926 collect(Fs&&... fs) {
927   auto ctx = std::make_shared<futures::detail::CollectVariadicContext<
928       typename std::decay<Fs>::type::value_type...>>();
929   futures::detail::collectVariadicHelper<
930       futures::detail::CollectVariadicContext>(ctx, std::forward<Fs>(fs)...);
931   return ctx->p.getFuture();
932 }
933
934 // collectAny (iterator)
935
936 template <class InputIterator>
937 Future<
938   std::pair<size_t,
939             Try<
940               typename
941               std::iterator_traits<InputIterator>::value_type::value_type>>>
942 collectAny(InputIterator first, InputIterator last) {
943   typedef
944     typename std::iterator_traits<InputIterator>::value_type::value_type T;
945
946   struct CollectAnyContext {
947     CollectAnyContext() {}
948     Promise<std::pair<size_t, Try<T>>> p;
949     std::atomic<bool> done {false};
950   };
951
952   auto ctx = std::make_shared<CollectAnyContext>();
953   mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
954     if (!ctx->done.exchange(true)) {
955       ctx->p.setValue(std::make_pair(i, std::move(t)));
956     }
957   });
958   return ctx->p.getFuture();
959 }
960
961 // collectAnyWithoutException (iterator)
962
963 template <class InputIterator>
964 Future<std::pair<
965     size_t,
966     typename std::iterator_traits<InputIterator>::value_type::value_type>>
967 collectAnyWithoutException(InputIterator first, InputIterator last) {
968   typedef
969       typename std::iterator_traits<InputIterator>::value_type::value_type T;
970
971   struct CollectAnyWithoutExceptionContext {
972     CollectAnyWithoutExceptionContext(){}
973     Promise<std::pair<size_t, T>> p;
974     std::atomic<bool> done{false};
975     std::atomic<size_t> nFulfilled{0};
976     size_t nTotal;
977   };
978
979   auto ctx = std::make_shared<CollectAnyWithoutExceptionContext>();
980   ctx->nTotal = size_t(std::distance(first, last));
981
982   mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
983     if (!t.hasException() && !ctx->done.exchange(true)) {
984       ctx->p.setValue(std::make_pair(i, std::move(t.value())));
985     } else if (++ctx->nFulfilled == ctx->nTotal) {
986       ctx->p.setException(t.exception());
987     }
988   });
989   return ctx->p.getFuture();
990 }
991
992 // collectN (iterator)
993
994 template <class InputIterator>
995 Future<std::vector<std::pair<size_t, Try<typename
996   std::iterator_traits<InputIterator>::value_type::value_type>>>>
997 collectN(InputIterator first, InputIterator last, size_t n) {
998   typedef typename
999     std::iterator_traits<InputIterator>::value_type::value_type T;
1000   typedef std::vector<std::pair<size_t, Try<T>>> V;
1001
1002   struct CollectNContext {
1003     V v;
1004     std::atomic<size_t> completed = {0};
1005     Promise<V> p;
1006   };
1007   auto ctx = std::make_shared<CollectNContext>();
1008
1009   if (size_t(std::distance(first, last)) < n) {
1010     ctx->p.setException(std::runtime_error("Not enough futures"));
1011   } else {
1012     // for each completed Future, increase count and add to vector, until we
1013     // have n completed futures at which point we fulfil our Promise with the
1014     // vector
1015     mapSetCallback<T>(first, last, [ctx, n](size_t i, Try<T>&& t) {
1016       auto c = ++ctx->completed;
1017       if (c <= n) {
1018         assert(ctx->v.size() < n);
1019         ctx->v.emplace_back(i, std::move(t));
1020         if (c == n) {
1021           ctx->p.setTry(Try<V>(std::move(ctx->v)));
1022         }
1023       }
1024     });
1025   }
1026
1027   return ctx->p.getFuture();
1028 }
1029
1030 // reduce (iterator)
1031
1032 template <class It, class T, class F>
1033 Future<T> reduce(It first, It last, T&& initial, F&& func) {
1034   if (first == last) {
1035     return makeFuture(std::move(initial));
1036   }
1037
1038   typedef typename std::iterator_traits<It>::value_type::value_type ItT;
1039   typedef typename std::conditional<
1040       futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
1041       Try<ItT>,
1042       ItT>::type Arg;
1043   typedef isTry<Arg> IsTry;
1044
1045   auto sfunc = std::make_shared<F>(std::move(func));
1046
1047   auto f = first->then(
1048       [ minitial = std::move(initial), sfunc ](Try<ItT> & head) mutable {
1049         return (*sfunc)(
1050             std::move(minitial), head.template get<IsTry::value, Arg&&>());
1051       });
1052
1053   for (++first; first != last; ++first) {
1054     f = collectAll(f, *first).then([sfunc](std::tuple<Try<T>, Try<ItT>>& t) {
1055       return (*sfunc)(std::move(std::get<0>(t).value()),
1056                   // Either return a ItT&& or a Try<ItT>&& depending
1057                   // on the type of the argument of func.
1058                   std::get<1>(t).template get<IsTry::value, Arg&&>());
1059     });
1060   }
1061
1062   return f;
1063 }
1064
1065 // window (collection)
1066
1067 template <class Collection, class F, class ItT, class Result>
1068 std::vector<Future<Result>>
1069 window(Collection input, F func, size_t n) {
1070   struct WindowContext {
1071     WindowContext(Collection&& i, F&& fn)
1072         : input_(std::move(i)), promises_(input_.size()),
1073           func_(std::move(fn))
1074       {}
1075     std::atomic<size_t> i_ {0};
1076     Collection input_;
1077     std::vector<Promise<Result>> promises_;
1078     F func_;
1079
1080     static inline void spawn(const std::shared_ptr<WindowContext>& ctx) {
1081       size_t i = ctx->i_++;
1082       if (i < ctx->input_.size()) {
1083         // Using setCallback_ directly since we don't need the Future
1084         ctx->func_(std::move(ctx->input_[i])).setCallback_(
1085           // ctx is captured by value
1086           [ctx, i](Try<Result>&& t) {
1087             ctx->promises_[i].setTry(std::move(t));
1088             // Chain another future onto this one
1089             spawn(std::move(ctx));
1090           });
1091       }
1092     }
1093   };
1094
1095   auto max = std::min(n, input.size());
1096
1097   auto ctx = std::make_shared<WindowContext>(
1098     std::move(input), std::move(func));
1099
1100   for (size_t i = 0; i < max; ++i) {
1101     // Start the first n Futures
1102     WindowContext::spawn(ctx);
1103   }
1104
1105   std::vector<Future<Result>> futures;
1106   futures.reserve(ctx->promises_.size());
1107   for (auto& promise : ctx->promises_) {
1108     futures.emplace_back(promise.getFuture());
1109   }
1110
1111   return futures;
1112 }
1113
1114 // reduce
1115
1116 template <class T>
1117 template <class I, class F>
1118 Future<I> Future<T>::reduce(I&& initial, F&& func) {
1119   return then([
1120     minitial = std::forward<I>(initial),
1121     mfunc = std::forward<F>(func)
1122   ](T& vals) mutable {
1123     auto ret = std::move(minitial);
1124     for (auto& val : vals) {
1125       ret = mfunc(std::move(ret), std::move(val));
1126     }
1127     return ret;
1128   });
1129 }
1130
1131 // unorderedReduce (iterator)
1132
1133 template <class It, class T, class F, class ItT, class Arg>
1134 Future<T> unorderedReduce(It first, It last, T initial, F func) {
1135   if (first == last) {
1136     return makeFuture(std::move(initial));
1137   }
1138
1139   typedef isTry<Arg> IsTry;
1140
1141   struct UnorderedReduceContext {
1142     UnorderedReduceContext(T&& memo, F&& fn, size_t n)
1143         : lock_(), memo_(makeFuture<T>(std::move(memo))),
1144           func_(std::move(fn)), numThens_(0), numFutures_(n), promise_()
1145       {}
1146     folly::MicroSpinLock lock_; // protects memo_ and numThens_
1147     Future<T> memo_;
1148     F func_;
1149     size_t numThens_; // how many Futures completed and called .then()
1150     size_t numFutures_; // how many Futures in total
1151     Promise<T> promise_;
1152   };
1153
1154   auto ctx = std::make_shared<UnorderedReduceContext>(
1155     std::move(initial), std::move(func), std::distance(first, last));
1156
1157   mapSetCallback<ItT>(
1158       first,
1159       last,
1160       [ctx](size_t /* i */, Try<ItT>&& t) {
1161         // Futures can be completed in any order, simultaneously.
1162         // To make this non-blocking, we create a new Future chain in
1163         // the order of completion to reduce the values.
1164         // The spinlock just protects chaining a new Future, not actually
1165         // executing the reduce, which should be really fast.
1166         folly::MSLGuard lock(ctx->lock_);
1167         ctx->memo_ =
1168             ctx->memo_.then([ ctx, mt = std::move(t) ](T && v) mutable {
1169               // Either return a ItT&& or a Try<ItT>&& depending
1170               // on the type of the argument of func.
1171               return ctx->func_(std::move(v),
1172                                 mt.template get<IsTry::value, Arg&&>());
1173             });
1174         if (++ctx->numThens_ == ctx->numFutures_) {
1175           // After reducing the value of the last Future, fulfill the Promise
1176           ctx->memo_.setCallback_(
1177               [ctx](Try<T>&& t2) { ctx->promise_.setValue(std::move(t2)); });
1178         }
1179       });
1180
1181   return ctx->promise_.getFuture();
1182 }
1183
1184 // within
1185
1186 template <class T>
1187 Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
1188   return within(dur, TimedOut(), tk);
1189 }
1190
1191 template <class T>
1192 template <class E>
1193 Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
1194
1195   struct Context {
1196     Context(E ex) : exception(std::move(ex)), promise() {}
1197     E exception;
1198     Future<Unit> thisFuture;
1199     Promise<T> promise;
1200     std::atomic<bool> token {false};
1201   };
1202
1203   if (this->isReady()) {
1204     return std::move(*this);
1205   }
1206
1207   std::shared_ptr<Timekeeper> tks;
1208   if (!tk) {
1209     tks = folly::detail::getTimekeeperSingleton();
1210     tk = DCHECK_NOTNULL(tks.get());
1211   }
1212
1213   auto ctx = std::make_shared<Context>(std::move(e));
1214
1215   ctx->thisFuture = this->then([ctx](Try<T>&& t) mutable {
1216     if (ctx->token.exchange(true) == false) {
1217       ctx->promise.setTry(std::move(t));
1218     }
1219   });
1220
1221   // Have time keeper use a weak ptr to hold ctx,
1222   // so that ctx can be deallocated as soon as the future job finished.
1223   tk->after(dur).then([weakCtx = to_weak_ptr(ctx)](Try<Unit> const& t) mutable {
1224     auto lockedCtx = weakCtx.lock();
1225     if (!lockedCtx) {
1226       // ctx already released. "this" completed first, cancel "after"
1227       return;
1228     }
1229     // "after" completed first, cancel "this"
1230     lockedCtx->thisFuture.raise(TimedOut());
1231     if (lockedCtx->token.exchange(true) == false) {
1232       if (t.hasException()) {
1233         lockedCtx->promise.setException(std::move(t.exception()));
1234       } else {
1235         lockedCtx->promise.setException(std::move(lockedCtx->exception));
1236       }
1237     }
1238   });
1239
1240   return ctx->promise.getFuture().via(this->getExecutor());
1241 }
1242
1243 // delayed
1244
1245 template <class T>
1246 Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
1247   return collectAll(*this, futures::sleep(dur, tk))
1248     .then([](std::tuple<Try<T>, Try<Unit>> tup) {
1249       Try<T>& t = std::get<0>(tup);
1250       return makeFuture<T>(std::move(t));
1251     });
1252 }
1253
1254 namespace futures {
1255 namespace detail {
1256
1257 template <class FutureType, typename T = typename FutureType::value_type>
1258 void waitImpl(FutureType& f) {
1259   // short-circuit if there's nothing to do
1260   if (f.isReady()) return;
1261
1262   FutureBatonType baton;
1263   f.setCallback_([&](const Try<T>& /* t */) { baton.post(); });
1264   baton.wait();
1265   assert(f.isReady());
1266 }
1267
1268 template <class FutureType, typename T = typename FutureType::value_type>
1269 void waitImpl(FutureType& f, Duration dur) {
1270   // short-circuit if there's nothing to do
1271   if (f.isReady()) {
1272     return;
1273   }
1274
1275   Promise<T> promise;
1276   auto ret = promise.getFuture();
1277   auto baton = std::make_shared<FutureBatonType>();
1278   f.setCallback_([ baton, promise = std::move(promise) ](Try<T> && t) mutable {
1279     promise.setTry(std::move(t));
1280     baton->post();
1281   });
1282   f = std::move(ret);
1283   if (baton->timed_wait(dur)) {
1284     assert(f.isReady());
1285   }
1286 }
1287
1288 template <class T>
1289 void waitViaImpl(Future<T>& f, DrivableExecutor* e) {
1290   // Set callback so to ensure that the via executor has something on it
1291   // so that once the preceding future triggers this callback, drive will
1292   // always have a callback to satisfy it
1293   if (f.isReady())
1294     return;
1295   f = f.via(e).then([](T&& t) { return std::move(t); });
1296   while (!f.isReady()) {
1297     e->drive();
1298   }
1299   assert(f.isReady());
1300 }
1301
1302 } // namespace detail
1303 } // namespace futures
1304
1305 template <class T>
1306 SemiFuture<T>& SemiFuture<T>::wait() & {
1307   futures::detail::waitImpl(*this);
1308   return *this;
1309 }
1310
1311 template <class T>
1312 SemiFuture<T>&& SemiFuture<T>::wait() && {
1313   futures::detail::waitImpl(*this);
1314   return std::move(*this);
1315 }
1316
1317 template <class T>
1318 SemiFuture<T>& SemiFuture<T>::wait(Duration dur) & {
1319   futures::detail::waitImpl(*this, dur);
1320   return *this;
1321 }
1322
1323 template <class T>
1324 SemiFuture<T>&& SemiFuture<T>::wait(Duration dur) && {
1325   futures::detail::waitImpl(*this, dur);
1326   return std::move(*this);
1327 }
1328
1329 template <class T>
1330 T SemiFuture<T>::get() {
1331   return std::move(wait().value());
1332 }
1333
1334 template <class T>
1335 T SemiFuture<T>::get(Duration dur) {
1336   wait(dur);
1337   if (this->isReady()) {
1338     return std::move(this->value());
1339   } else {
1340     throwTimedOut();
1341   }
1342 }
1343
1344 template <class T>
1345 Future<T>& Future<T>::wait() & {
1346   futures::detail::waitImpl(*this);
1347   return *this;
1348 }
1349
1350 template <class T>
1351 Future<T>&& Future<T>::wait() && {
1352   futures::detail::waitImpl(*this);
1353   return std::move(*this);
1354 }
1355
1356 template <class T>
1357 Future<T>& Future<T>::wait(Duration dur) & {
1358   futures::detail::waitImpl(*this, dur);
1359   return *this;
1360 }
1361
1362 template <class T>
1363 Future<T>&& Future<T>::wait(Duration dur) && {
1364   futures::detail::waitImpl(*this, dur);
1365   return std::move(*this);
1366 }
1367
1368 template <class T>
1369 Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
1370   futures::detail::waitViaImpl(*this, e);
1371   return *this;
1372 }
1373
1374 template <class T>
1375 Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
1376   futures::detail::waitViaImpl(*this, e);
1377   return std::move(*this);
1378 }
1379
1380 template <class T>
1381 T Future<T>::getVia(DrivableExecutor* e) {
1382   return std::move(waitVia(e).value());
1383 }
1384
1385 namespace futures {
1386 namespace detail {
1387 template <class T>
1388 struct TryEquals {
1389   static bool equals(const Try<T>& t1, const Try<T>& t2) {
1390     return t1.value() == t2.value();
1391   }
1392 };
1393 } // namespace detail
1394 } // namespace futures
1395
1396 template <class T>
1397 Future<bool> Future<T>::willEqual(Future<T>& f) {
1398   return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
1399     if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
1400       return futures::detail::TryEquals<T>::equals(
1401           std::get<0>(t), std::get<1>(t));
1402     } else {
1403       return false;
1404       }
1405   });
1406 }
1407
1408 template <class T>
1409 template <class F>
1410 Future<T> Future<T>::filter(F&& predicate) {
1411   return this->then([p = std::forward<F>(predicate)](T val) {
1412     T const& valConstRef = val;
1413     if (!p(valConstRef)) {
1414       throwPredicateDoesNotObtain();
1415     }
1416     return val;
1417   });
1418 }
1419
1420 template <class F>
1421 inline Future<Unit> when(bool p, F&& thunk) {
1422   return p ? std::forward<F>(thunk)().unit() : makeFuture();
1423 }
1424
1425 template <class P, class F>
1426 Future<Unit> whileDo(P&& predicate, F&& thunk) {
1427   if (predicate()) {
1428     auto future = thunk();
1429     return future.then([
1430       predicate = std::forward<P>(predicate),
1431       thunk = std::forward<F>(thunk)
1432     ]() mutable {
1433       return whileDo(std::forward<P>(predicate), std::forward<F>(thunk));
1434     });
1435   }
1436   return makeFuture();
1437 }
1438
1439 template <class F>
1440 Future<Unit> times(const int n, F&& thunk) {
1441   return folly::whileDo(
1442       [ n, count = std::make_unique<std::atomic<int>>(0) ]() mutable {
1443         return count->fetch_add(1) < n;
1444       },
1445       std::forward<F>(thunk));
1446 }
1447
1448 namespace futures {
1449   template <class It, class F, class ItT, class Result>
1450   std::vector<Future<Result>> map(It first, It last, F func) {
1451     std::vector<Future<Result>> results;
1452     for (auto it = first; it != last; it++) {
1453       results.push_back(it->then(func));
1454     }
1455     return results;
1456   }
1457 }
1458
1459 // Instantiate the most common Future types to save compile time
1460 extern template class Future<Unit>;
1461 extern template class Future<bool>;
1462 extern template class Future<int>;
1463 extern template class Future<int64_t>;
1464 extern template class Future<std::string>;
1465 extern template class Future<double>;
1466 } // namespace folly