34940cedb39d57c410c5182356a86128dc38430a
[folly.git] / folly / futures / Future-inl.h
1 /*
2  * Copyright 2014 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 <chrono>
20 #include <thread>
21
22 #include <folly/Baton.h>
23 #include <folly/futures/detail/Core.h>
24 #include <folly/futures/Timekeeper.h>
25
26 namespace folly {
27
28 class Timekeeper;
29
30 namespace detail {
31   Timekeeper* getTimekeeperSingleton();
32 }
33
34 template <typename T>
35 struct isFuture {
36   static const bool value = false;
37 };
38
39 template <typename T>
40 struct isFuture<Future<T> > {
41   static const bool value = true;
42 };
43
44 template <class T>
45 Future<T>::Future(Future<T>&& other) noexcept : core_(nullptr) {
46   *this = std::move(other);
47 }
48
49 template <class T>
50 Future<T>& Future<T>::operator=(Future<T>&& other) {
51   std::swap(core_, other.core_);
52   return *this;
53 }
54
55 template <class T>
56 Future<T>::~Future() {
57   detach();
58 }
59
60 template <class T>
61 void Future<T>::detach() {
62   if (core_) {
63     core_->detachFuture();
64     core_ = nullptr;
65   }
66 }
67
68 template <class T>
69 void Future<T>::throwIfInvalid() const {
70   if (!core_)
71     throw NoState();
72 }
73
74 template <class T>
75 template <class F>
76 void Future<T>::setCallback_(F&& func) {
77   throwIfInvalid();
78   core_->setCallback(std::move(func));
79 }
80
81 // Variant: f.then([](Try<T>&& t){ return t.value(); });
82 template <class T>
83 template <class F>
84 typename std::enable_if<
85   !isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
86   Future<typename std::result_of<F(Try<T>&&)>::type> >::type
87 Future<T>::then(F&& func) {
88   typedef typename std::result_of<F(Try<T>&&)>::type B;
89
90   throwIfInvalid();
91
92   // wrap these so we can move them into the lambda
93   folly::MoveWrapper<Promise<B>> p;
94   folly::MoveWrapper<F> funcm(std::forward<F>(func));
95
96   // grab the Future now before we lose our handle on the Promise
97   auto f = p->getFuture();
98
99   /* This is a bit tricky.
100
101      We can't just close over *this in case this Future gets moved. So we
102      make a new dummy Future. We could figure out something more
103      sophisticated that avoids making a new Future object when it can, as an
104      optimization. But this is correct.
105
106      core_ can't be moved, it is explicitly disallowed (as is copying). But
107      if there's ever a reason to allow it, this is one place that makes that
108      assumption and would need to be fixed. We use a standard shared pointer
109      for core_ (by copying it in), which means in essence obj holds a shared
110      pointer to itself.  But this shouldn't leak because Promise will not
111      outlive the continuation, because Promise will setException() with a
112      broken Promise if it is destructed before completed. We could use a
113      weak pointer but it would have to be converted to a shared pointer when
114      func is executed (because the Future returned by func may possibly
115      persist beyond the callback, if it gets moved), and so it is an
116      optimization to just make it shared from the get-go.
117
118      We have to move in the Promise and func using the MoveWrapper
119      hack. (func could be copied but it's a big drag on perf).
120
121      Two subtle but important points about this design. detail::Core has no
122      back pointers to Future or Promise, so if Future or Promise get moved
123      (and they will be moved in performant code) we don't have to do
124      anything fancy. And because we store the continuation in the
125      detail::Core, not in the Future, we can execute the continuation even
126      after the Future has gone out of scope. This is an intentional design
127      decision. It is likely we will want to be able to cancel a continuation
128      in some circumstances, but I think it should be explicit not implicit
129      in the destruction of the Future used to create it.
130      */
131   setCallback_(
132     [p, funcm](Try<T>&& t) mutable {
133       p->fulfil([&]() {
134         return (*funcm)(std::move(t));
135       });
136     });
137
138   return f;
139 }
140
141 // Variant: f.then([](T&& t){ return t; });
142 template <class T>
143 template <class F>
144 typename std::enable_if<
145   !std::is_same<T, void>::value &&
146   !isFuture<typename std::result_of<
147     F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
148   Future<typename std::result_of<
149     F(typename detail::AliasIfVoid<T>::type&&)>::type> >::type
150 Future<T>::then(F&& func) {
151   typedef typename std::result_of<F(T&&)>::type B;
152
153   throwIfInvalid();
154
155   folly::MoveWrapper<Promise<B>> p;
156   folly::MoveWrapper<F> funcm(std::forward<F>(func));
157   auto f = p->getFuture();
158
159   setCallback_(
160     [p, funcm](Try<T>&& t) mutable {
161       if (t.hasException()) {
162         p->setException(std::move(t.exception()));
163       } else {
164         p->fulfil([&]() {
165           return (*funcm)(std::move(t.value()));
166         });
167       }
168     });
169
170   return f;
171 }
172
173 // Variant: f.then([](){ return; });
174 template <class T>
175 template <class F>
176 typename std::enable_if<
177   std::is_same<T, void>::value &&
178   !isFuture<typename std::result_of<F()>::type>::value,
179   Future<typename std::result_of<F()>::type> >::type
180 Future<T>::then(F&& func) {
181   typedef typename std::result_of<F()>::type B;
182
183   throwIfInvalid();
184
185   folly::MoveWrapper<Promise<B>> p;
186   folly::MoveWrapper<F> funcm(std::forward<F>(func));
187   auto f = p->getFuture();
188
189   setCallback_(
190     [p, funcm](Try<T>&& t) mutable {
191       if (t.hasException()) {
192         p->setException(std::move(t.exception()));
193       } else {
194         p->fulfil([&]() {
195           return (*funcm)();
196         });
197       }
198     });
199
200   return f;
201 }
202
203 // Variant: f.then([](Try<T>&& t){ return makeFuture<T>(t.value()); });
204 template <class T>
205 template <class F>
206 typename std::enable_if<
207   isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
208   Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
209 Future<T>::then(F&& func) {
210   typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
211
212   throwIfInvalid();
213
214   // wrap these so we can move them into the lambda
215   folly::MoveWrapper<Promise<B>> p;
216   folly::MoveWrapper<F> funcm(std::forward<F>(func));
217
218   // grab the Future now before we lose our handle on the Promise
219   auto f = p->getFuture();
220
221   setCallback_(
222     [p, funcm](Try<T>&& t) mutable {
223       try {
224         auto f2 = (*funcm)(std::move(t));
225         // that didn't throw, now we can steal p
226         f2.setCallback_([p](Try<B>&& b) mutable {
227           p->fulfilTry(std::move(b));
228         });
229       } catch (const std::exception& e) {
230         p->setException(exception_wrapper(std::current_exception(), e));
231       } catch (...) {
232         p->setException(exception_wrapper(std::current_exception()));
233       }
234     });
235
236   return f;
237 }
238
239 // Variant: f.then([](T&& t){ return makeFuture<T>(t); });
240 template <class T>
241 template <class F>
242 typename std::enable_if<
243   !std::is_same<T, void>::value &&
244   isFuture<typename std::result_of<
245     F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
246   Future<typename std::result_of<
247     F(typename detail::AliasIfVoid<T>::type&&)>::type::value_type> >::type
248 Future<T>::then(F&& func) {
249   typedef typename std::result_of<F(T&&)>::type::value_type B;
250
251   throwIfInvalid();
252
253   folly::MoveWrapper<Promise<B>> p;
254   folly::MoveWrapper<F> funcm(std::forward<F>(func));
255   auto f = p->getFuture();
256
257   setCallback_(
258     [p, funcm](Try<T>&& t) mutable {
259       if (t.hasException()) {
260         p->setException(std::move(t.exception()));
261       } else {
262         try {
263           auto f2 = (*funcm)(std::move(t.value()));
264           f2.setCallback_([p](Try<B>&& b) mutable {
265             p->fulfilTry(std::move(b));
266           });
267         } catch (const std::exception& e) {
268           p->setException(exception_wrapper(std::current_exception(), e));
269         } catch (...) {
270           p->setException(exception_wrapper(std::current_exception()));
271         }
272       }
273     });
274
275   return f;
276 }
277
278 // Variant: f.then([](){ return makeFuture(); });
279 template <class T>
280 template <class F>
281 typename std::enable_if<
282   std::is_same<T, void>::value &&
283   isFuture<typename std::result_of<F()>::type>::value,
284   Future<typename std::result_of<F()>::type::value_type> >::type
285 Future<T>::then(F&& func) {
286   typedef typename std::result_of<F()>::type::value_type B;
287
288   throwIfInvalid();
289
290   folly::MoveWrapper<Promise<B>> p;
291   folly::MoveWrapper<F> funcm(std::forward<F>(func));
292
293   auto f = p->getFuture();
294
295   setCallback_(
296     [p, funcm](Try<T>&& t) mutable {
297       if (t.hasException()) {
298         p->setException(t.exception());
299       } else {
300         try {
301           auto f2 = (*funcm)();
302           f2.setCallback_([p](Try<B>&& b) mutable {
303             p->fulfilTry(std::move(b));
304           });
305         } catch (const std::exception& e) {
306           p->setException(exception_wrapper(std::current_exception(), e));
307         } catch (...) {
308           p->setException(exception_wrapper(std::current_exception()));
309         }
310       }
311     });
312
313   return f;
314 }
315
316 template <class T>
317 Future<void> Future<T>::then() {
318   return then([] (Try<T>&& t) {});
319 }
320
321 // onError where the callback returns T
322 template <class T>
323 template <class F>
324 typename std::enable_if<
325   !detail::Extract<F>::ReturnsFuture::value,
326   Future<T>>::type
327 Future<T>::onError(F&& func) {
328   typedef typename detail::Extract<F>::FirstArg Exn;
329   static_assert(
330       std::is_same<typename detail::Extract<F>::RawReturn, T>::value,
331       "Return type of onError callback must be T or Future<T>");
332
333   Promise<T> p;
334   auto f = p.getFuture();
335   auto pm = folly::makeMoveWrapper(std::move(p));
336   auto funcm = folly::makeMoveWrapper(std::move(func));
337   setCallback_([pm, funcm](Try<T>&& t) mutable {
338     if (!t.template withException<Exn>([&] (Exn& e) {
339           pm->fulfil([&]{
340             return (*funcm)(e);
341           });
342         })) {
343       pm->fulfilTry(std::move(t));
344     }
345   });
346
347   return f;
348 }
349
350 // onError where the callback returns Future<T>
351 template <class T>
352 template <class F>
353 typename std::enable_if<
354   detail::Extract<F>::ReturnsFuture::value,
355   Future<T>>::type
356 Future<T>::onError(F&& func) {
357   static_assert(
358       std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
359       "Return type of onError callback must be T or Future<T>");
360   typedef typename detail::Extract<F>::FirstArg Exn;
361
362   Promise<T> p;
363   auto f = p.getFuture();
364   auto pm = folly::makeMoveWrapper(std::move(p));
365   auto funcm = folly::makeMoveWrapper(std::move(func));
366   setCallback_([pm, funcm](Try<T>&& t) mutable {
367     if (!t.template withException<Exn>([&] (Exn& e) {
368           try {
369             auto f2 = (*funcm)(e);
370             f2.setCallback_([pm](Try<T>&& t2) mutable {
371               pm->fulfilTry(std::move(t2));
372             });
373           } catch (const std::exception& e2) {
374             pm->setException(exception_wrapper(std::current_exception(), e2));
375           } catch (...) {
376             pm->setException(exception_wrapper(std::current_exception()));
377           }
378         })) {
379       pm->fulfilTry(std::move(t));
380     }
381   });
382
383   return f;
384 }
385
386 template <class T>
387 typename std::add_lvalue_reference<T>::type Future<T>::value() {
388   throwIfInvalid();
389
390   return core_->getTry().value();
391 }
392
393 template <class T>
394 typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
395   throwIfInvalid();
396
397   return core_->getTry().value();
398 }
399
400 template <class T>
401 Try<T>& Future<T>::getTry() {
402   throwIfInvalid();
403
404   return core_->getTry();
405 }
406
407 template <class T>
408 template <typename Executor>
409 inline Future<T> Future<T>::via(Executor* executor) && {
410   throwIfInvalid();
411
412   this->deactivate();
413   core_->setExecutor(executor);
414
415   return std::move(*this);
416 }
417
418 template <class T>
419 template <typename Executor>
420 inline Future<T> Future<T>::via(Executor* executor) & {
421   throwIfInvalid();
422
423   MoveWrapper<Promise<T>> p;
424   auto f = p->getFuture();
425   then([p](Try<T>&& t) mutable { p->fulfilTry(std::move(t)); });
426   return std::move(f).via(executor);
427 }
428
429 template <class T>
430 bool Future<T>::isReady() const {
431   throwIfInvalid();
432   return core_->ready();
433 }
434
435 template <class T>
436 void Future<T>::raise(exception_wrapper exception) {
437   core_->raise(std::move(exception));
438 }
439
440 // makeFuture
441
442 template <class T>
443 Future<typename std::decay<T>::type> makeFuture(T&& t) {
444   Promise<typename std::decay<T>::type> p;
445   p.setValue(std::forward<T>(t));
446   return p.getFuture();
447 }
448
449 inline // for multiple translation units
450 Future<void> makeFuture() {
451   Promise<void> p;
452   p.setValue();
453   return p.getFuture();
454 }
455
456 template <class F>
457 auto makeFutureTry(
458     F&& func,
459     typename std::enable_if<!std::is_reference<F>::value, bool>::type sdf)
460     -> Future<decltype(func())> {
461   Promise<decltype(func())> p;
462   p.fulfil(
463     [&func]() {
464       return (func)();
465     });
466   return p.getFuture();
467 }
468
469 template <class F>
470 auto makeFutureTry(F const& func) -> Future<decltype(func())> {
471   F copy = func;
472   return makeFutureTry(std::move(copy));
473 }
474
475 template <class T>
476 Future<T> makeFuture(std::exception_ptr const& e) {
477   Promise<T> p;
478   p.setException(e);
479   return p.getFuture();
480 }
481
482 template <class T>
483 Future<T> makeFuture(exception_wrapper ew) {
484   Promise<T> p;
485   p.setException(std::move(ew));
486   return p.getFuture();
487 }
488
489 template <class T, class E>
490 typename std::enable_if<std::is_base_of<std::exception, E>::value,
491                         Future<T>>::type
492 makeFuture(E const& e) {
493   Promise<T> p;
494   p.setException(make_exception_wrapper<E>(e));
495   return p.getFuture();
496 }
497
498 template <class T>
499 Future<T> makeFuture(Try<T>&& t) {
500   if (t.hasException()) {
501     return makeFuture<T>(std::move(t.exception()));
502   } else {
503     return makeFuture<T>(std::move(t.value()));
504   }
505 }
506
507 template <>
508 inline Future<void> makeFuture(Try<void>&& t) {
509   if (t.hasException()) {
510     return makeFuture<void>(std::move(t.exception()));
511   } else {
512     return makeFuture();
513   }
514 }
515
516 // via
517 template <typename Executor>
518 Future<void> via(Executor* executor) {
519   return makeFuture().via(executor);
520 }
521
522 // when (variadic)
523
524 template <typename... Fs>
525 typename detail::VariadicContext<
526   typename std::decay<Fs>::type::value_type...>::type
527 whenAll(Fs&&... fs)
528 {
529   auto ctx =
530     new detail::VariadicContext<typename std::decay<Fs>::type::value_type...>();
531   ctx->total = sizeof...(fs);
532   auto f_saved = ctx->p.getFuture();
533   detail::whenAllVariadicHelper(ctx,
534     std::forward<typename std::decay<Fs>::type>(fs)...);
535   return f_saved;
536 }
537
538 // when (iterator)
539
540 template <class InputIterator>
541 Future<
542   std::vector<
543   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
544 whenAll(InputIterator first, InputIterator last)
545 {
546   typedef
547     typename std::iterator_traits<InputIterator>::value_type::value_type T;
548
549   if (first >= last) {
550     return makeFuture(std::vector<Try<T>>());
551   }
552   size_t n = std::distance(first, last);
553
554   auto ctx = new detail::WhenAllContext<T>();
555
556   ctx->results.resize(n);
557
558   auto f_saved = ctx->p.getFuture();
559
560   for (size_t i = 0; first != last; ++first, ++i) {
561      assert(i < n);
562      auto& f = *first;
563      f.setCallback_([ctx, i, n](Try<T>&& t) {
564          ctx->results[i] = std::move(t);
565          if (++ctx->count == n) {
566            ctx->p.setValue(std::move(ctx->results));
567            delete ctx;
568          }
569        });
570   }
571
572   return f_saved;
573 }
574
575 template <class InputIterator>
576 Future<
577   std::pair<size_t,
578             Try<
579               typename
580               std::iterator_traits<InputIterator>::value_type::value_type> > >
581 whenAny(InputIterator first, InputIterator last) {
582   typedef
583     typename std::iterator_traits<InputIterator>::value_type::value_type T;
584
585   auto ctx = new detail::WhenAnyContext<T>(std::distance(first, last));
586   auto f_saved = ctx->p.getFuture();
587
588   for (size_t i = 0; first != last; first++, i++) {
589     auto& f = *first;
590     f.setCallback_([i, ctx](Try<T>&& t) {
591       if (!ctx->done.exchange(true)) {
592         ctx->p.setValue(std::make_pair(i, std::move(t)));
593       }
594       ctx->decref();
595     });
596   }
597
598   return f_saved;
599 }
600
601 template <class InputIterator>
602 Future<std::vector<std::pair<size_t, Try<typename
603   std::iterator_traits<InputIterator>::value_type::value_type>>>>
604 whenN(InputIterator first, InputIterator last, size_t n) {
605   typedef typename
606     std::iterator_traits<InputIterator>::value_type::value_type T;
607   typedef std::vector<std::pair<size_t, Try<T>>> V;
608
609   struct ctx_t {
610     V v;
611     size_t completed;
612     Promise<V> p;
613   };
614   auto ctx = std::make_shared<ctx_t>();
615   ctx->completed = 0;
616
617   // for each completed Future, increase count and add to vector, until we
618   // have n completed futures at which point we fulfil our Promise with the
619   // vector
620   auto it = first;
621   size_t i = 0;
622   while (it != last) {
623     it->then([ctx, n, i](Try<T>&& t) {
624       auto& v = ctx->v;
625       auto c = ++ctx->completed;
626       if (c <= n) {
627         assert(ctx->v.size() < n);
628         v.push_back(std::make_pair(i, std::move(t)));
629         if (c == n) {
630           ctx->p.fulfilTry(Try<V>(std::move(v)));
631         }
632       }
633     });
634
635     it++;
636     i++;
637   }
638
639   if (i < n) {
640     ctx->p.setException(std::runtime_error("Not enough futures"));
641   }
642
643   return ctx->p.getFuture();
644 }
645
646 namespace {
647   template <class T>
648   void getWaitHelper(Future<T>* f) {
649     // If we already have a value do the cheap thing
650     if (f->isReady()) {
651       return;
652     }
653
654     folly::Baton<> baton;
655     f->then([&](Try<T> const&) {
656       baton.post();
657     });
658     baton.wait();
659   }
660
661   template <class T>
662   Future<T> getWaitTimeoutHelper(Future<T>* f, Duration dur) {
663     // TODO make and use variadic whenAny #5877971
664     Promise<T> p;
665     auto token = std::make_shared<std::atomic<bool>>();
666     folly::Baton<> baton;
667
668     folly::detail::getTimekeeperSingleton()->after(dur)
669       .then([&,token](Try<void> const& t) {
670         if (token->exchange(true) == false) {
671           try {
672             t.value();
673             p.setException(TimedOut());
674           } catch (std::exception const& e) {
675             p.setException(exception_wrapper(std::current_exception(), e));
676           } catch (...) {
677             p.setException(exception_wrapper(std::current_exception()));
678           }
679           baton.post();
680         }
681       });
682
683     f->then([&, token](Try<T>&& t) {
684       if (token->exchange(true) == false) {
685         p.fulfilTry(std::move(t));
686         baton.post();
687       }
688     });
689
690     baton.wait();
691     return p.getFuture();
692   }
693 }
694
695 template <class T>
696 T Future<T>::get() {
697   getWaitHelper(this);
698
699   // Big assumption here: the then() call above, since it doesn't move out
700   // the value, leaves us with a value to return here. This would be a big
701   // no-no in user code, but I'm invoking internal developer privilege. This
702   // is slightly more efficient (save a move()) especially if there's an
703   // exception (save a throw).
704   return std::move(value());
705 }
706
707 template <>
708 inline void Future<void>::get() {
709   getWaitHelper(this);
710   value();
711 }
712
713 template <class T>
714 T Future<T>::get(Duration dur) {
715   return std::move(getWaitTimeoutHelper(this, dur).value());
716 }
717
718 template <>
719 inline void Future<void>::get(Duration dur) {
720   getWaitTimeoutHelper(this, dur).value();
721 }
722
723 template <class T>
724 T Future<T>::getVia(DrivableExecutor* e) {
725   while (!isReady()) {
726     e->drive();
727   }
728   return std::move(value());
729 }
730
731 template <>
732 inline void Future<void>::getVia(DrivableExecutor* e) {
733   while (!isReady()) {
734     e->drive();
735   }
736   value();
737 }
738
739 template <class T>
740 Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
741   return within(dur, TimedOut(), tk);
742 }
743
744 template <class T>
745 template <class E>
746 Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
747
748   struct Context {
749     Context(E ex) : exception(std::move(ex)), promise(), token(false) {}
750     E exception;
751     Promise<T> promise;
752     std::atomic<bool> token;
753   };
754   auto ctx = std::make_shared<Context>(std::move(e));
755
756   if (!tk) {
757     tk = folly::detail::getTimekeeperSingleton();
758   }
759
760   tk->after(dur)
761     .then([ctx](Try<void> const& t) {
762       if (ctx->token.exchange(true) == false) {
763         try {
764           t.throwIfFailed();
765           ctx->promise.setException(std::move(ctx->exception));
766         } catch (std::exception const& e2) {
767           ctx->promise.setException(
768               exception_wrapper(std::current_exception(), e2));
769         } catch (...) {
770           ctx->promise.setException(
771               exception_wrapper(std::current_exception()));
772         }
773       }
774     });
775
776   this->then([ctx](Try<T>&& t) {
777     if (ctx->token.exchange(true) == false) {
778       ctx->promise.fulfilTry(std::move(t));
779     }
780   });
781
782   return ctx->promise.getFuture();
783 }
784
785 template <class T>
786 Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
787   return whenAll(*this, futures::sleep(dur, tk))
788     .then([](std::tuple<Try<T>, Try<void>> tup) {
789       Try<T>& t = std::get<0>(tup);
790       return makeFuture<T>(std::move(t));
791     });
792 }
793
794 template <class T>
795 Future<T> Future<T>::wait() {
796   Baton<> baton;
797   auto done = then([&](Try<T> t) {
798     baton.post();
799     return makeFuture(std::move(t));
800   });
801   baton.wait();
802   while (!done.isReady()) {
803     // There's a race here between the return here and the actual finishing of
804     // the future. f is completed, but the setup may not have finished on done
805     // after the baton has posted.
806     std::this_thread::yield();
807   }
808   return done;
809 }
810
811 template <class T>
812 Future<T> Future<T>::wait(Duration dur) {
813   auto baton = std::make_shared<Baton<>>();
814   auto done = then([baton](Try<T> t) {
815     baton->post();
816     return makeFuture(std::move(t));
817   });
818   baton->timed_wait(std::chrono::system_clock::now() + dur);
819   return done;
820 }
821
822 template <class T>
823 Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
824   while (!isReady()) {
825     e->drive();
826   }
827   return *this;
828 }
829
830 template <class T>
831 Future<T> Future<T>::waitVia(DrivableExecutor* e) && {
832   while (!isReady()) {
833     e->drive();
834   }
835   return std::move(*this);
836 }
837
838 }
839
840 // I haven't included a Future<T&> specialization because I don't forsee us
841 // using it, however it is not difficult to add when needed. Refer to
842 // Future<void> for guidance. std::future and boost::future code would also be
843 // instructive.