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