2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <folly/experimental/fibers/Baton.h>
23 #include <folly/Optional.h>
24 #include <folly/futures/detail/Core.h>
25 #include <folly/futures/Timekeeper.h>
32 Timekeeper* getTimekeeperSingleton();
36 Future<T>::Future(Future<T>&& other) noexcept : core_(other.core_) {
37 other.core_ = nullptr;
41 Future<T>& Future<T>::operator=(Future<T>&& other) noexcept {
42 std::swap(core_, other.core_);
47 template <class T2, typename>
48 Future<T>::Future(T2&& val) : core_(nullptr) {
50 p.setValue(std::forward<T2>(val));
51 *this = p.getFuture();
56 typename std::enable_if<
57 folly::is_void_or_unit<T2>::value,
59 Future<T>::Future() : core_(nullptr) {
62 *this = p.getFuture();
67 Future<T>::~Future() {
72 void Future<T>::detach() {
74 core_->detachFuture();
80 void Future<T>::throwIfInvalid() const {
87 void Future<T>::setCallback_(F&& func) {
89 core_->setCallback(std::move(func));
96 typename std::enable_if<isFuture<F>::value,
97 Future<typename isFuture<T>::Inner>>::type
99 return then([](Future<typename isFuture<T>::Inner> internal_future) {
100 return internal_future;
106 // Variant: returns a value
107 // e.g. f.then([](Try<T>&& t){ return t.value(); });
109 template <typename F, typename R, bool isTry, typename... Args>
110 typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
111 Future<T>::thenImplementation(F func, detail::argResult<isTry, F, Args...>) {
112 static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
113 typedef typename R::ReturnsFuture::Inner B;
117 // wrap these so we can move them into the lambda
118 folly::MoveWrapper<Promise<B>> p;
119 folly::MoveWrapper<F> funcm(std::forward<F>(func));
121 // grab the Future now before we lose our handle on the Promise
122 auto f = p->getFuture();
124 f.setExecutor(getExecutor());
127 /* This is a bit tricky.
129 We can't just close over *this in case this Future gets moved. So we
130 make a new dummy Future. We could figure out something more
131 sophisticated that avoids making a new Future object when it can, as an
132 optimization. But this is correct.
134 core_ can't be moved, it is explicitly disallowed (as is copying). But
135 if there's ever a reason to allow it, this is one place that makes that
136 assumption and would need to be fixed. We use a standard shared pointer
137 for core_ (by copying it in), which means in essence obj holds a shared
138 pointer to itself. But this shouldn't leak because Promise will not
139 outlive the continuation, because Promise will setException() with a
140 broken Promise if it is destructed before completed. We could use a
141 weak pointer but it would have to be converted to a shared pointer when
142 func is executed (because the Future returned by func may possibly
143 persist beyond the callback, if it gets moved), and so it is an
144 optimization to just make it shared from the get-go.
146 We have to move in the Promise and func using the MoveWrapper
147 hack. (func could be copied but it's a big drag on perf).
149 Two subtle but important points about this design. detail::Core has no
150 back pointers to Future or Promise, so if Future or Promise get moved
151 (and they will be moved in performant code) we don't have to do
152 anything fancy. And because we store the continuation in the
153 detail::Core, not in the Future, we can execute the continuation even
154 after the Future has gone out of scope. This is an intentional design
155 decision. It is likely we will want to be able to cancel a continuation
156 in some circumstances, but I think it should be explicit not implicit
157 in the destruction of the Future used to create it.
160 [p, funcm](Try<T>&& t) mutable {
161 if (!isTry && t.hasException()) {
162 p->setException(std::move(t.exception()));
165 return (*funcm)(t.template get<isTry, Args>()...);
173 // Variant: returns a Future
174 // e.g. f.then([](T&& t){ return makeFuture<T>(t); });
176 template <typename F, typename R, bool isTry, typename... Args>
177 typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
178 Future<T>::thenImplementation(F func, detail::argResult<isTry, F, Args...>) {
179 static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
180 typedef typename R::ReturnsFuture::Inner B;
184 // wrap these so we can move them into the lambda
185 folly::MoveWrapper<Promise<B>> p;
186 folly::MoveWrapper<F> funcm(std::forward<F>(func));
188 // grab the Future now before we lose our handle on the Promise
189 auto f = p->getFuture();
191 f.setExecutor(getExecutor());
195 [p, funcm](Try<T>&& t) mutable {
196 if (!isTry && t.hasException()) {
197 p->setException(std::move(t.exception()));
200 auto f2 = (*funcm)(t.template get<isTry, Args>()...);
201 // that didn't throw, now we can steal p
202 f2.setCallback_([p](Try<B>&& b) mutable {
203 p->setTry(std::move(b));
205 } catch (const std::exception& e) {
206 p->setException(exception_wrapper(std::current_exception(), e));
208 p->setException(exception_wrapper(std::current_exception()));
216 template <typename T>
217 template <typename R, typename Caller, typename... Args>
218 Future<typename isFuture<R>::Inner>
219 Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
220 typedef typename std::remove_cv<
221 typename std::remove_reference<
222 typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg;
223 return then([instance, func](Try<T>&& t){
224 return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
229 template <class Executor, class Arg, class... Args>
230 auto Future<T>::then(Executor* x, Arg&& arg, Args&&... args)
231 -> decltype(this->then(std::forward<Arg>(arg),
232 std::forward<Args>(args)...))
234 auto oldX = getExecutor();
236 return this->then(std::forward<Arg>(arg), std::forward<Args>(args)...).
241 Future<void> Future<T>::then() {
242 return then([] (Try<T>&& t) {});
245 // onError where the callback returns T
248 typename std::enable_if<
249 !detail::callableWith<F, exception_wrapper>::value &&
250 !detail::Extract<F>::ReturnsFuture::value,
252 Future<T>::onError(F&& func) {
253 typedef typename detail::Extract<F>::FirstArg Exn;
255 std::is_same<typename detail::Extract<F>::RawReturn, T>::value,
256 "Return type of onError callback must be T or Future<T>");
259 auto f = p.getFuture();
260 auto pm = folly::makeMoveWrapper(std::move(p));
261 auto funcm = folly::makeMoveWrapper(std::move(func));
262 setCallback_([pm, funcm](Try<T>&& t) mutable {
263 if (!t.template withException<Exn>([&] (Exn& e) {
268 pm->setTry(std::move(t));
275 // onError where the callback returns Future<T>
278 typename std::enable_if<
279 !detail::callableWith<F, exception_wrapper>::value &&
280 detail::Extract<F>::ReturnsFuture::value,
282 Future<T>::onError(F&& func) {
284 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
285 "Return type of onError callback must be T or Future<T>");
286 typedef typename detail::Extract<F>::FirstArg Exn;
289 auto f = p.getFuture();
290 auto pm = folly::makeMoveWrapper(std::move(p));
291 auto funcm = folly::makeMoveWrapper(std::move(func));
292 setCallback_([pm, funcm](Try<T>&& t) mutable {
293 if (!t.template withException<Exn>([&] (Exn& e) {
295 auto f2 = (*funcm)(e);
296 f2.setCallback_([pm](Try<T>&& t2) mutable {
297 pm->setTry(std::move(t2));
299 } catch (const std::exception& e2) {
300 pm->setException(exception_wrapper(std::current_exception(), e2));
302 pm->setException(exception_wrapper(std::current_exception()));
305 pm->setTry(std::move(t));
314 Future<T> Future<T>::ensure(F func) {
315 MoveWrapper<F> funcw(std::move(func));
316 return this->then([funcw](Try<T>&& t) {
318 return makeFuture(std::move(t));
324 Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
325 auto funcw = folly::makeMoveWrapper(std::forward<F>(func));
326 return within(dur, tk)
327 .onError([funcw](TimedOut const&) { return (*funcw)(); });
332 typename std::enable_if<
333 detail::callableWith<F, exception_wrapper>::value &&
334 detail::Extract<F>::ReturnsFuture::value,
336 Future<T>::onError(F&& func) {
338 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
339 "Return type of onError callback must be T or Future<T>");
342 auto f = p.getFuture();
343 auto pm = folly::makeMoveWrapper(std::move(p));
344 auto funcm = folly::makeMoveWrapper(std::move(func));
345 setCallback_([pm, funcm](Try<T> t) mutable {
346 if (t.hasException()) {
348 auto f2 = (*funcm)(std::move(t.exception()));
349 f2.setCallback_([pm](Try<T> t2) mutable {
350 pm->setTry(std::move(t2));
352 } catch (const std::exception& e2) {
353 pm->setException(exception_wrapper(std::current_exception(), e2));
355 pm->setException(exception_wrapper(std::current_exception()));
358 pm->setTry(std::move(t));
365 // onError(exception_wrapper) that returns T
368 typename std::enable_if<
369 detail::callableWith<F, exception_wrapper>::value &&
370 !detail::Extract<F>::ReturnsFuture::value,
372 Future<T>::onError(F&& func) {
374 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
375 "Return type of onError callback must be T or Future<T>");
378 auto f = p.getFuture();
379 auto pm = folly::makeMoveWrapper(std::move(p));
380 auto funcm = folly::makeMoveWrapper(std::move(func));
381 setCallback_([pm, funcm](Try<T> t) mutable {
382 if (t.hasException()) {
384 return (*funcm)(std::move(t.exception()));
387 pm->setTry(std::move(t));
395 typename std::add_lvalue_reference<T>::type Future<T>::value() {
398 return core_->getTry().value();
402 typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
405 return core_->getTry().value();
409 Try<T>& Future<T>::getTry() {
412 return core_->getTry();
416 Optional<Try<T>> Future<T>::poll() {
418 if (core_->ready()) {
419 o = std::move(core_->getTry());
425 inline Future<T> Future<T>::via(Executor* executor, int8_t priority) && {
428 setExecutor(executor, priority);
430 return std::move(*this);
434 inline Future<T> Future<T>::via(Executor* executor, int8_t priority) & {
437 MoveWrapper<Promise<T>> p;
438 auto f = p->getFuture();
439 then([p](Try<T>&& t) mutable { p->setTry(std::move(t)); });
440 return std::move(f).via(executor, priority);
444 bool Future<T>::isReady() const {
446 return core_->ready();
450 void Future<T>::raise(exception_wrapper exception) {
451 core_->raise(std::move(exception));
457 Future<typename std::decay<T>::type> makeFuture(T&& t) {
458 Promise<typename std::decay<T>::type> p;
459 p.setValue(std::forward<T>(t));
460 return p.getFuture();
463 inline // for multiple translation units
464 Future<void> makeFuture() {
467 return p.getFuture();
473 typename std::enable_if<!std::is_reference<F>::value, bool>::type sdf)
474 -> Future<decltype(func())> {
475 Promise<decltype(func())> p;
480 return p.getFuture();
484 auto makeFutureWith(F const& func) -> Future<decltype(func())> {
486 return makeFutureWith(std::move(copy));
490 Future<T> makeFuture(std::exception_ptr const& e) {
493 return p.getFuture();
497 Future<T> makeFuture(exception_wrapper ew) {
499 p.setException(std::move(ew));
500 return p.getFuture();
503 template <class T, class E>
504 typename std::enable_if<std::is_base_of<std::exception, E>::value,
506 makeFuture(E const& e) {
508 p.setException(make_exception_wrapper<E>(e));
509 return p.getFuture();
513 Future<T> makeFuture(Try<T>&& t) {
514 Promise<typename std::decay<T>::type> p;
515 p.setTry(std::move(t));
516 return p.getFuture();
520 inline Future<void> makeFuture(Try<void>&& t) {
521 if (t.hasException()) {
522 return makeFuture<void>(std::move(t.exception()));
529 Future<void> via(Executor* executor, int8_t priority) {
530 return makeFuture().via(executor, priority);
533 // mapSetCallback calls func(i, Try<T>) when every future completes
535 template <class T, class InputIterator, class F>
536 void mapSetCallback(InputIterator first, InputIterator last, F func) {
537 for (size_t i = 0; first != last; ++first, ++i) {
538 first->setCallback_([func, i](Try<T>&& t) {
539 func(i, std::move(t));
544 // collectAll (variadic)
546 template <typename... Fs>
547 typename detail::VariadicContext<
548 typename std::decay<Fs>::type::value_type...>::type
549 collectAll(Fs&&... fs) {
550 auto ctx = std::make_shared<detail::VariadicContext<
551 typename std::decay<Fs>::type::value_type...>>();
552 detail::collectAllVariadicHelper(ctx,
553 std::forward<typename std::decay<Fs>::type>(fs)...);
554 return ctx->p.getFuture();
557 // collectAll (iterator)
559 template <class InputIterator>
562 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
563 collectAll(InputIterator first, InputIterator last) {
565 typename std::iterator_traits<InputIterator>::value_type::value_type T;
567 struct CollectAllContext {
568 CollectAllContext(int n) : results(n) {}
569 ~CollectAllContext() {
570 p.setValue(std::move(results));
572 Promise<std::vector<Try<T>>> p;
573 std::vector<Try<T>> results;
576 auto ctx = std::make_shared<CollectAllContext>(std::distance(first, last));
577 mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
578 ctx->results[i] = std::move(t);
580 return ctx->p.getFuture();
585 template <typename T>
586 struct CollectContext {
587 struct Nothing { explicit Nothing(int n) {} };
589 using Result = typename std::conditional<
590 std::is_void<T>::value,
592 std::vector<T>>::type;
594 using InternalResult = typename std::conditional<
595 std::is_void<T>::value,
597 std::vector<Optional<T>>>::type;
599 explicit CollectContext(int n) : result(n) {}
601 if (!threw.exchange(true)) {
602 // map Optional<T> -> T
603 std::vector<T> finalResult;
604 finalResult.reserve(result.size());
605 std::transform(result.begin(), result.end(),
606 std::back_inserter(finalResult),
607 [](Optional<T>& o) { return std::move(o.value()); });
608 p.setValue(std::move(finalResult));
611 inline void setPartialResult(size_t i, Try<T>& t) {
612 result[i] = std::move(t.value());
615 InternalResult result;
616 std::atomic<bool> threw;
619 // Specialize for void (implementations in Future.cpp)
622 CollectContext<void>::~CollectContext();
625 void CollectContext<void>::setPartialResult(size_t i, Try<void>& t);
629 template <class InputIterator>
630 Future<typename detail::CollectContext<
631 typename std::iterator_traits<InputIterator>::value_type::value_type>::Result>
632 collect(InputIterator first, InputIterator last) {
634 typename std::iterator_traits<InputIterator>::value_type::value_type T;
636 auto ctx = std::make_shared<detail::CollectContext<T>>(
637 std::distance(first, last));
638 mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
639 if (t.hasException()) {
640 if (!ctx->threw.exchange(true)) {
641 ctx->p.setException(std::move(t.exception()));
643 } else if (!ctx->threw) {
644 ctx->setPartialResult(i, t);
647 return ctx->p.getFuture();
650 template <class InputIterator>
655 std::iterator_traits<InputIterator>::value_type::value_type>>>
656 collectAny(InputIterator first, InputIterator last) {
658 typename std::iterator_traits<InputIterator>::value_type::value_type T;
660 struct CollectAnyContext {
661 CollectAnyContext(size_t n) : done(false) {};
662 Promise<std::pair<size_t, Try<T>>> p;
663 std::atomic<bool> done;
666 auto ctx = std::make_shared<CollectAnyContext>(std::distance(first, last));
667 mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
668 if (!ctx->done.exchange(true)) {
669 ctx->p.setValue(std::make_pair(i, std::move(t)));
672 return ctx->p.getFuture();
675 template <class InputIterator>
676 Future<std::vector<std::pair<size_t, Try<typename
677 std::iterator_traits<InputIterator>::value_type::value_type>>>>
678 collectN(InputIterator first, InputIterator last, size_t n) {
680 std::iterator_traits<InputIterator>::value_type::value_type T;
681 typedef std::vector<std::pair<size_t, Try<T>>> V;
683 struct CollectNContext {
685 std::atomic<size_t> completed = {0};
688 auto ctx = std::make_shared<CollectNContext>();
690 if (std::distance(first, last) < n) {
691 ctx->p.setException(std::runtime_error("Not enough futures"));
693 // for each completed Future, increase count and add to vector, until we
694 // have n completed futures at which point we fulfil our Promise with the
696 mapSetCallback<T>(first, last, [ctx, n](size_t i, Try<T>&& t) {
697 auto c = ++ctx->completed;
699 assert(ctx->v.size() < n);
700 ctx->v.push_back(std::make_pair(i, std::move(t)));
702 ctx->p.setTry(Try<V>(std::move(ctx->v)));
708 return ctx->p.getFuture();
711 template <class It, class T, class F>
712 Future<T> reduce(It first, It last, T&& initial, F&& func) {
714 return makeFuture(std::move(initial));
717 typedef typename std::iterator_traits<It>::value_type::value_type ItT;
718 typedef typename std::conditional<
719 detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type Arg;
720 typedef isTry<Arg> IsTry;
722 folly::MoveWrapper<T> minitial(std::move(initial));
723 auto sfunc = std::make_shared<F>(std::move(func));
725 auto f = first->then([minitial, sfunc](Try<ItT>& head) mutable {
726 return (*sfunc)(std::move(*minitial),
727 head.template get<IsTry::value, Arg&&>());
730 for (++first; first != last; ++first) {
731 f = collectAll(f, *first).then([sfunc](std::tuple<Try<T>, Try<ItT>>& t) {
732 return (*sfunc)(std::move(std::get<0>(t).value()),
733 // Either return a ItT&& or a Try<ItT>&& depending
734 // on the type of the argument of func.
735 std::get<1>(t).template get<IsTry::value, Arg&&>());
742 template <class Collection, class F, class ItT, class Result>
743 std::vector<Future<Result>>
744 window(Collection input, F func, size_t n) {
745 struct WindowContext {
746 WindowContext(Collection&& i, F&& fn)
747 : i_(0), input_(std::move(i)), promises_(input_.size()),
750 std::atomic<size_t> i_;
752 std::vector<Promise<Result>> promises_;
755 static inline void spawn(const std::shared_ptr<WindowContext>& ctx) {
756 size_t i = ctx->i_++;
757 if (i < ctx->input_.size()) {
758 // Using setCallback_ directly since we don't need the Future
759 ctx->func_(std::move(ctx->input_[i])).setCallback_(
760 // ctx is captured by value
761 [ctx, i](Try<Result>&& t) {
762 ctx->promises_[i].setTry(std::move(t));
763 // Chain another future onto this one
764 spawn(std::move(ctx));
770 auto max = std::min(n, input.size());
772 auto ctx = std::make_shared<WindowContext>(
773 std::move(input), std::move(func));
775 for (size_t i = 0; i < max; ++i) {
776 // Start the first n Futures
777 WindowContext::spawn(ctx);
780 std::vector<Future<Result>> futures;
781 futures.reserve(ctx->promises_.size());
782 for (auto& promise : ctx->promises_) {
783 futures.emplace_back(promise.getFuture());
790 template <class I, class F>
791 Future<I> Future<T>::reduce(I&& initial, F&& func) {
792 folly::MoveWrapper<I> minitial(std::move(initial));
793 folly::MoveWrapper<F> mfunc(std::move(func));
794 return then([minitial, mfunc](T& vals) mutable {
795 auto ret = std::move(*minitial);
796 for (auto& val : vals) {
797 ret = (*mfunc)(std::move(ret), std::move(val));
803 template <class It, class T, class F, class ItT, class Arg>
804 Future<T> unorderedReduce(It first, It last, T initial, F func) {
806 return makeFuture(std::move(initial));
809 typedef isTry<Arg> IsTry;
811 struct UnorderedReduceContext {
812 UnorderedReduceContext(T&& memo, F&& fn, size_t n)
813 : lock_(), memo_(makeFuture<T>(std::move(memo))),
814 func_(std::move(fn)), numThens_(0), numFutures_(n), promise_()
816 folly::MicroSpinLock lock_; // protects memo_ and numThens_
819 size_t numThens_; // how many Futures completed and called .then()
820 size_t numFutures_; // how many Futures in total
824 auto ctx = std::make_shared<UnorderedReduceContext>(
825 std::move(initial), std::move(func), std::distance(first, last));
827 mapSetCallback<ItT>(first, last, [ctx](size_t i, Try<ItT>&& t) {
828 folly::MoveWrapper<Try<ItT>> mt(std::move(t));
829 // Futures can be completed in any order, simultaneously.
830 // To make this non-blocking, we create a new Future chain in
831 // the order of completion to reduce the values.
832 // The spinlock just protects chaining a new Future, not actually
833 // executing the reduce, which should be really fast.
834 folly::MSLGuard lock(ctx->lock_);
835 ctx->memo_ = ctx->memo_.then([ctx, mt](T&& v) mutable {
836 // Either return a ItT&& or a Try<ItT>&& depending
837 // on the type of the argument of func.
838 return ctx->func_(std::move(v), mt->template get<IsTry::value, Arg&&>());
840 if (++ctx->numThens_ == ctx->numFutures_) {
841 // After reducing the value of the last Future, fulfill the Promise
842 ctx->memo_.setCallback_([ctx](Try<T>&& t2) {
843 ctx->promise_.setValue(std::move(t2));
848 return ctx->promise_.getFuture();
852 Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
853 return within(dur, TimedOut(), tk);
858 Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
861 Context(E ex) : exception(std::move(ex)), promise(), token(false) {}
864 std::atomic<bool> token;
866 auto ctx = std::make_shared<Context>(std::move(e));
869 tk = folly::detail::getTimekeeperSingleton();
873 .then([ctx](Try<void> const& t) {
874 if (ctx->token.exchange(true) == false) {
875 if (t.hasException()) {
876 ctx->promise.setException(std::move(t.exception()));
878 ctx->promise.setException(std::move(ctx->exception));
883 this->then([ctx](Try<T>&& t) {
884 if (ctx->token.exchange(true) == false) {
885 ctx->promise.setTry(std::move(t));
889 return ctx->promise.getFuture();
893 Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
894 return collectAll(*this, futures::sleep(dur, tk))
895 .then([](std::tuple<Try<T>, Try<void>> tup) {
896 Try<T>& t = std::get<0>(tup);
897 return makeFuture<T>(std::move(t));
904 void waitImpl(Future<T>& f) {
905 // short-circuit if there's nothing to do
906 if (f.isReady()) return;
908 folly::fibers::Baton baton;
909 f = f.then([&](Try<T> t) {
911 return makeFuture(std::move(t));
915 // There's a race here between the return here and the actual finishing of
916 // the future. f is completed, but the setup may not have finished on done
917 // after the baton has posted.
918 while (!f.isReady()) {
919 std::this_thread::yield();
924 void waitImpl(Future<T>& f, Duration dur) {
925 // short-circuit if there's nothing to do
926 if (f.isReady()) return;
928 auto baton = std::make_shared<folly::fibers::Baton>();
929 f = f.then([baton](Try<T> t) {
931 return makeFuture(std::move(t));
934 // Let's preserve the invariant that if we did not timeout (timed_wait returns
935 // true), then the returned Future is complete when it is returned to the
936 // caller. We need to wait out the race for that Future to complete.
937 if (baton->timed_wait(dur)) {
938 while (!f.isReady()) {
939 std::this_thread::yield();
945 void waitViaImpl(Future<T>& f, DrivableExecutor* e) {
946 while (!f.isReady()) {
954 Future<T>& Future<T>::wait() & {
955 detail::waitImpl(*this);
960 Future<T>&& Future<T>::wait() && {
961 detail::waitImpl(*this);
962 return std::move(*this);
966 Future<T>& Future<T>::wait(Duration dur) & {
967 detail::waitImpl(*this, dur);
972 Future<T>&& Future<T>::wait(Duration dur) && {
973 detail::waitImpl(*this, dur);
974 return std::move(*this);
978 Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
979 detail::waitViaImpl(*this, e);
984 Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
985 detail::waitViaImpl(*this, e);
986 return std::move(*this);
991 return std::move(wait().value());
995 inline void Future<void>::get() {
1000 T Future<T>::get(Duration dur) {
1003 return std::move(value());
1010 inline void Future<void>::get(Duration dur) {
1020 T Future<T>::getVia(DrivableExecutor* e) {
1021 return std::move(waitVia(e).value());
1025 inline void Future<void>::getVia(DrivableExecutor* e) {
1032 static bool equals(const Try<T>& t1, const Try<T>& t2) {
1033 return t1.value() == t2.value();
1038 struct TryEquals<void> {
1039 static bool equals(const Try<void>& t1, const Try<void>& t2) {
1046 Future<bool> Future<T>::willEqual(Future<T>& f) {
1047 return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
1048 if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
1049 return detail::TryEquals<T>::equals(std::get<0>(t), std::get<1>(t));
1058 Future<T> Future<T>::filter(F predicate) {
1059 auto p = folly::makeMoveWrapper(std::move(predicate));
1060 return this->then([p](T val) {
1061 T const& valConstRef = val;
1062 if (!(*p)(valConstRef)) {
1063 throw PredicateDoesNotObtain();
1070 template <class Callback>
1071 auto Future<T>::thenMulti(Callback&& fn)
1072 -> decltype(this->then(std::forward<Callback>(fn))) {
1073 // thenMulti with one callback is just a then
1074 return then(std::forward<Callback>(fn));
1078 template <class Callback, class... Callbacks>
1079 auto Future<T>::thenMulti(Callback&& fn, Callbacks&&... fns)
1080 -> decltype(this->then(std::forward<Callback>(fn)).
1081 thenMulti(std::forward<Callbacks>(fns)...)) {
1082 // thenMulti with two callbacks is just then(a).thenMulti(b, ...)
1083 return then(std::forward<Callback>(fn)).
1084 thenMulti(std::forward<Callbacks>(fns)...);
1088 template <class Callback, class... Callbacks>
1089 auto Future<T>::thenMultiWithExecutor(Executor* x, Callback&& fn,
1091 -> decltype(this->then(std::forward<Callback>(fn)).
1092 thenMulti(std::forward<Callbacks>(fns)...)) {
1093 // thenMultiExecutor with two callbacks is
1094 // via(x).then(a).thenMulti(b, ...).via(oldX)
1095 auto oldX = getExecutor();
1097 return then(std::forward<Callback>(fn)).
1098 thenMulti(std::forward<Callbacks>(fns)...).via(oldX);
1102 template <class Callback>
1103 auto Future<T>::thenMultiWithExecutor(Executor* x, Callback&& fn)
1104 -> decltype(this->then(std::forward<Callback>(fn))) {
1105 // thenMulti with one callback is just a then with an executor
1106 return then(x, std::forward<Callback>(fn));
1110 template <class It, class F, class ItT, class Result>
1111 std::vector<Future<Result>> map(It first, It last, F func) {
1112 std::vector<Future<Result>> results;
1113 for (auto it = first; it != last; it++) {
1114 results.push_back(it->then(func));
1120 // Instantiate the most common Future types to save compile time
1121 extern template class Future<void>;
1122 extern template class Future<bool>;
1123 extern template class Future<int>;
1124 extern template class Future<int64_t>;
1125 extern template class Future<std::string>;
1126 extern template class Future<double>;
1128 } // namespace folly
1130 // I haven't included a Future<T&> specialization because I don't forsee us
1131 // using it, however it is not difficult to add when needed. Refer to
1132 // Future<void> for guidance. std::future and boost::future code would also be