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