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 p->setInterruptHandler(core_->getInterruptHandler());
120 folly::MoveWrapper<F> funcm(std::forward<F>(func));
122 // grab the Future now before we lose our handle on the Promise
123 auto f = p->getFuture();
125 f.setExecutor(getExecutor());
128 /* This is a bit tricky.
130 We can't just close over *this in case this Future gets moved. So we
131 make a new dummy Future. We could figure out something more
132 sophisticated that avoids making a new Future object when it can, as an
133 optimization. But this is correct.
135 core_ can't be moved, it is explicitly disallowed (as is copying). But
136 if there's ever a reason to allow it, this is one place that makes that
137 assumption and would need to be fixed. We use a standard shared pointer
138 for core_ (by copying it in), which means in essence obj holds a shared
139 pointer to itself. But this shouldn't leak because Promise will not
140 outlive the continuation, because Promise will setException() with a
141 broken Promise if it is destructed before completed. We could use a
142 weak pointer but it would have to be converted to a shared pointer when
143 func is executed (because the Future returned by func may possibly
144 persist beyond the callback, if it gets moved), and so it is an
145 optimization to just make it shared from the get-go.
147 We have to move in the Promise and func using the MoveWrapper
148 hack. (func could be copied but it's a big drag on perf).
150 Two subtle but important points about this design. detail::Core has no
151 back pointers to Future or Promise, so if Future or Promise get moved
152 (and they will be moved in performant code) we don't have to do
153 anything fancy. And because we store the continuation in the
154 detail::Core, not in the Future, we can execute the continuation even
155 after the Future has gone out of scope. This is an intentional design
156 decision. It is likely we will want to be able to cancel a continuation
157 in some circumstances, but I think it should be explicit not implicit
158 in the destruction of the Future used to create it.
161 [p, funcm](Try<T>&& t) mutable {
162 if (!isTry && t.hasException()) {
163 p->setException(std::move(t.exception()));
166 return (*funcm)(t.template get<isTry, Args>()...);
174 // Variant: returns a Future
175 // e.g. f.then([](T&& t){ return makeFuture<T>(t); });
177 template <typename F, typename R, bool isTry, typename... Args>
178 typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
179 Future<T>::thenImplementation(F func, detail::argResult<isTry, F, Args...>) {
180 static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
181 typedef typename R::ReturnsFuture::Inner B;
185 // wrap these so we can move them into the lambda
186 folly::MoveWrapper<Promise<B>> p;
187 folly::MoveWrapper<F> funcm(std::forward<F>(func));
189 // grab the Future now before we lose our handle on the Promise
190 auto f = p->getFuture();
192 f.setExecutor(getExecutor());
196 [p, funcm](Try<T>&& t) mutable {
197 if (!isTry && t.hasException()) {
198 p->setException(std::move(t.exception()));
201 auto f2 = (*funcm)(t.template get<isTry, Args>()...);
202 // that didn't throw, now we can steal p
203 f2.setCallback_([p](Try<B>&& b) mutable {
204 p->setTry(std::move(b));
206 } catch (const std::exception& e) {
207 p->setException(exception_wrapper(std::current_exception(), e));
209 p->setException(exception_wrapper(std::current_exception()));
217 template <typename T>
218 template <typename R, typename Caller, typename... Args>
219 Future<typename isFuture<R>::Inner>
220 Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
221 typedef typename std::remove_cv<
222 typename std::remove_reference<
223 typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg;
224 return then([instance, func](Try<T>&& t){
225 return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
230 template <class Executor, class Arg, class... Args>
231 auto Future<T>::then(Executor* x, Arg&& arg, Args&&... args)
232 -> decltype(this->then(std::forward<Arg>(arg),
233 std::forward<Args>(args)...))
235 auto oldX = getExecutor();
237 return this->then(std::forward<Arg>(arg), std::forward<Args>(args)...).
242 Future<void> Future<T>::then() {
243 return then([] (Try<T>&& t) {});
246 // onError where the callback returns T
249 typename std::enable_if<
250 !detail::callableWith<F, exception_wrapper>::value &&
251 !detail::Extract<F>::ReturnsFuture::value,
253 Future<T>::onError(F&& func) {
254 typedef typename detail::Extract<F>::FirstArg Exn;
256 std::is_same<typename detail::Extract<F>::RawReturn, T>::value,
257 "Return type of onError callback must be T or Future<T>");
260 auto f = p.getFuture();
261 auto pm = folly::makeMoveWrapper(std::move(p));
262 auto funcm = folly::makeMoveWrapper(std::move(func));
263 setCallback_([pm, funcm](Try<T>&& t) mutable {
264 if (!t.template withException<Exn>([&] (Exn& e) {
269 pm->setTry(std::move(t));
276 // onError where the callback returns Future<T>
279 typename std::enable_if<
280 !detail::callableWith<F, exception_wrapper>::value &&
281 detail::Extract<F>::ReturnsFuture::value,
283 Future<T>::onError(F&& func) {
285 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
286 "Return type of onError callback must be T or Future<T>");
287 typedef typename detail::Extract<F>::FirstArg Exn;
290 auto f = p.getFuture();
291 auto pm = folly::makeMoveWrapper(std::move(p));
292 auto funcm = folly::makeMoveWrapper(std::move(func));
293 setCallback_([pm, funcm](Try<T>&& t) mutable {
294 if (!t.template withException<Exn>([&] (Exn& e) {
296 auto f2 = (*funcm)(e);
297 f2.setCallback_([pm](Try<T>&& t2) mutable {
298 pm->setTry(std::move(t2));
300 } catch (const std::exception& e2) {
301 pm->setException(exception_wrapper(std::current_exception(), e2));
303 pm->setException(exception_wrapper(std::current_exception()));
306 pm->setTry(std::move(t));
315 Future<T> Future<T>::ensure(F func) {
316 MoveWrapper<F> funcw(std::move(func));
317 return this->then([funcw](Try<T>&& t) {
319 return makeFuture(std::move(t));
325 Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
326 auto funcw = folly::makeMoveWrapper(std::forward<F>(func));
327 return within(dur, tk)
328 .onError([funcw](TimedOut const&) { return (*funcw)(); });
333 typename std::enable_if<
334 detail::callableWith<F, exception_wrapper>::value &&
335 detail::Extract<F>::ReturnsFuture::value,
337 Future<T>::onError(F&& func) {
339 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
340 "Return type of onError callback must be T or Future<T>");
343 auto f = p.getFuture();
344 auto pm = folly::makeMoveWrapper(std::move(p));
345 auto funcm = folly::makeMoveWrapper(std::move(func));
346 setCallback_([pm, funcm](Try<T> t) mutable {
347 if (t.hasException()) {
349 auto f2 = (*funcm)(std::move(t.exception()));
350 f2.setCallback_([pm](Try<T> t2) mutable {
351 pm->setTry(std::move(t2));
353 } catch (const std::exception& e2) {
354 pm->setException(exception_wrapper(std::current_exception(), e2));
356 pm->setException(exception_wrapper(std::current_exception()));
359 pm->setTry(std::move(t));
366 // onError(exception_wrapper) that returns T
369 typename std::enable_if<
370 detail::callableWith<F, exception_wrapper>::value &&
371 !detail::Extract<F>::ReturnsFuture::value,
373 Future<T>::onError(F&& func) {
375 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
376 "Return type of onError callback must be T or Future<T>");
379 auto f = p.getFuture();
380 auto pm = folly::makeMoveWrapper(std::move(p));
381 auto funcm = folly::makeMoveWrapper(std::move(func));
382 setCallback_([pm, funcm](Try<T> t) mutable {
383 if (t.hasException()) {
385 return (*funcm)(std::move(t.exception()));
388 pm->setTry(std::move(t));
396 typename std::add_lvalue_reference<T>::type Future<T>::value() {
399 return core_->getTry().value();
403 typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
406 return core_->getTry().value();
410 Try<T>& Future<T>::getTry() {
413 return core_->getTry();
417 Optional<Try<T>> Future<T>::poll() {
419 if (core_->ready()) {
420 o = std::move(core_->getTry());
426 inline Future<T> Future<T>::via(Executor* executor, int8_t priority) && {
429 setExecutor(executor, priority);
431 return std::move(*this);
435 inline Future<T> Future<T>::via(Executor* executor, int8_t priority) & {
438 MoveWrapper<Promise<T>> p;
439 auto f = p->getFuture();
440 then([p](Try<T>&& t) mutable { p->setTry(std::move(t)); });
441 return std::move(f).via(executor, priority);
445 bool Future<T>::isReady() const {
447 return core_->ready();
451 void Future<T>::raise(exception_wrapper exception) {
452 core_->raise(std::move(exception));
458 Future<typename std::decay<T>::type> makeFuture(T&& t) {
459 Promise<typename std::decay<T>::type> p;
460 p.setValue(std::forward<T>(t));
461 return p.getFuture();
464 inline // for multiple translation units
465 Future<void> makeFuture() {
468 return p.getFuture();
474 typename std::enable_if<!std::is_reference<F>::value, bool>::type sdf)
475 -> Future<decltype(func())> {
476 Promise<decltype(func())> p;
481 return p.getFuture();
485 auto makeFutureWith(F const& func) -> Future<decltype(func())> {
487 return makeFutureWith(std::move(copy));
491 Future<T> makeFuture(std::exception_ptr const& e) {
494 return p.getFuture();
498 Future<T> makeFuture(exception_wrapper ew) {
500 p.setException(std::move(ew));
501 return p.getFuture();
504 template <class T, class E>
505 typename std::enable_if<std::is_base_of<std::exception, E>::value,
507 makeFuture(E const& e) {
509 p.setException(make_exception_wrapper<E>(e));
510 return p.getFuture();
514 Future<T> makeFuture(Try<T>&& t) {
515 Promise<typename std::decay<T>::type> p;
516 p.setTry(std::move(t));
517 return p.getFuture();
521 inline Future<void> makeFuture(Try<void>&& t) {
522 if (t.hasException()) {
523 return makeFuture<void>(std::move(t.exception()));
530 Future<void> via(Executor* executor, int8_t priority) {
531 return makeFuture().via(executor, priority);
534 // mapSetCallback calls func(i, Try<T>) when every future completes
536 template <class T, class InputIterator, class F>
537 void mapSetCallback(InputIterator first, InputIterator last, F func) {
538 for (size_t i = 0; first != last; ++first, ++i) {
539 first->setCallback_([func, i](Try<T>&& t) {
540 func(i, std::move(t));
545 // collectAll (variadic)
547 template <typename... Fs>
548 typename detail::VariadicContext<
549 typename std::decay<Fs>::type::value_type...>::type
550 collectAll(Fs&&... fs) {
551 auto ctx = std::make_shared<detail::VariadicContext<
552 typename std::decay<Fs>::type::value_type...>>();
553 detail::collectAllVariadicHelper(ctx,
554 std::forward<typename std::decay<Fs>::type>(fs)...);
555 return ctx->p.getFuture();
558 // collectAll (iterator)
560 template <class InputIterator>
563 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
564 collectAll(InputIterator first, InputIterator last) {
566 typename std::iterator_traits<InputIterator>::value_type::value_type T;
568 struct CollectAllContext {
569 CollectAllContext(int n) : results(n) {}
570 ~CollectAllContext() {
571 p.setValue(std::move(results));
573 Promise<std::vector<Try<T>>> p;
574 std::vector<Try<T>> results;
577 auto ctx = std::make_shared<CollectAllContext>(std::distance(first, last));
578 mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
579 ctx->results[i] = std::move(t);
581 return ctx->p.getFuture();
586 template <typename T>
587 struct CollectContext {
588 struct Nothing { explicit Nothing(int n) {} };
590 using Result = typename std::conditional<
591 std::is_void<T>::value,
593 std::vector<T>>::type;
595 using InternalResult = typename std::conditional<
596 std::is_void<T>::value,
598 std::vector<Optional<T>>>::type;
600 explicit CollectContext(int n) : result(n) {}
602 if (!threw.exchange(true)) {
603 // map Optional<T> -> T
604 std::vector<T> finalResult;
605 finalResult.reserve(result.size());
606 std::transform(result.begin(), result.end(),
607 std::back_inserter(finalResult),
608 [](Optional<T>& o) { return std::move(o.value()); });
609 p.setValue(std::move(finalResult));
612 inline void setPartialResult(size_t i, Try<T>& t) {
613 result[i] = std::move(t.value());
616 InternalResult result;
617 std::atomic<bool> threw;
620 // Specialize for void (implementations in Future.cpp)
623 CollectContext<void>::~CollectContext();
626 void CollectContext<void>::setPartialResult(size_t i, Try<void>& t);
630 template <class InputIterator>
631 Future<typename detail::CollectContext<
632 typename std::iterator_traits<InputIterator>::value_type::value_type>::Result>
633 collect(InputIterator first, InputIterator last) {
635 typename std::iterator_traits<InputIterator>::value_type::value_type T;
637 auto ctx = std::make_shared<detail::CollectContext<T>>(
638 std::distance(first, last));
639 mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
640 if (t.hasException()) {
641 if (!ctx->threw.exchange(true)) {
642 ctx->p.setException(std::move(t.exception()));
644 } else if (!ctx->threw) {
645 ctx->setPartialResult(i, t);
648 return ctx->p.getFuture();
651 template <class InputIterator>
656 std::iterator_traits<InputIterator>::value_type::value_type>>>
657 collectAny(InputIterator first, InputIterator last) {
659 typename std::iterator_traits<InputIterator>::value_type::value_type T;
661 struct CollectAnyContext {
662 CollectAnyContext(size_t n) : done(false) {};
663 Promise<std::pair<size_t, Try<T>>> p;
664 std::atomic<bool> done;
667 auto ctx = std::make_shared<CollectAnyContext>(std::distance(first, last));
668 mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
669 if (!ctx->done.exchange(true)) {
670 ctx->p.setValue(std::make_pair(i, std::move(t)));
673 return ctx->p.getFuture();
676 template <class InputIterator>
677 Future<std::vector<std::pair<size_t, Try<typename
678 std::iterator_traits<InputIterator>::value_type::value_type>>>>
679 collectN(InputIterator first, InputIterator last, size_t n) {
681 std::iterator_traits<InputIterator>::value_type::value_type T;
682 typedef std::vector<std::pair<size_t, Try<T>>> V;
684 struct CollectNContext {
686 std::atomic<size_t> completed = {0};
689 auto ctx = std::make_shared<CollectNContext>();
691 if (size_t(std::distance(first, last)) < n) {
692 ctx->p.setException(std::runtime_error("Not enough futures"));
694 // for each completed Future, increase count and add to vector, until we
695 // have n completed futures at which point we fulfil our Promise with the
697 mapSetCallback<T>(first, last, [ctx, n](size_t i, Try<T>&& t) {
698 auto c = ++ctx->completed;
700 assert(ctx->v.size() < n);
701 ctx->v.push_back(std::make_pair(i, std::move(t)));
703 ctx->p.setTry(Try<V>(std::move(ctx->v)));
709 return ctx->p.getFuture();
712 template <class It, class T, class F>
713 Future<T> reduce(It first, It last, T&& initial, F&& func) {
715 return makeFuture(std::move(initial));
718 typedef typename std::iterator_traits<It>::value_type::value_type ItT;
719 typedef typename std::conditional<
720 detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type Arg;
721 typedef isTry<Arg> IsTry;
723 folly::MoveWrapper<T> minitial(std::move(initial));
724 auto sfunc = std::make_shared<F>(std::move(func));
726 auto f = first->then([minitial, sfunc](Try<ItT>& head) mutable {
727 return (*sfunc)(std::move(*minitial),
728 head.template get<IsTry::value, Arg&&>());
731 for (++first; first != last; ++first) {
732 f = collectAll(f, *first).then([sfunc](std::tuple<Try<T>, Try<ItT>>& t) {
733 return (*sfunc)(std::move(std::get<0>(t).value()),
734 // Either return a ItT&& or a Try<ItT>&& depending
735 // on the type of the argument of func.
736 std::get<1>(t).template get<IsTry::value, Arg&&>());
743 template <class Collection, class F, class ItT, class Result>
744 std::vector<Future<Result>>
745 window(Collection input, F func, size_t n) {
746 struct WindowContext {
747 WindowContext(Collection&& i, F&& fn)
748 : i_(0), input_(std::move(i)), promises_(input_.size()),
751 std::atomic<size_t> i_;
753 std::vector<Promise<Result>> promises_;
756 static inline void spawn(const std::shared_ptr<WindowContext>& ctx) {
757 size_t i = ctx->i_++;
758 if (i < ctx->input_.size()) {
759 // Using setCallback_ directly since we don't need the Future
760 ctx->func_(std::move(ctx->input_[i])).setCallback_(
761 // ctx is captured by value
762 [ctx, i](Try<Result>&& t) {
763 ctx->promises_[i].setTry(std::move(t));
764 // Chain another future onto this one
765 spawn(std::move(ctx));
771 auto max = std::min(n, input.size());
773 auto ctx = std::make_shared<WindowContext>(
774 std::move(input), std::move(func));
776 for (size_t i = 0; i < max; ++i) {
777 // Start the first n Futures
778 WindowContext::spawn(ctx);
781 std::vector<Future<Result>> futures;
782 futures.reserve(ctx->promises_.size());
783 for (auto& promise : ctx->promises_) {
784 futures.emplace_back(promise.getFuture());
791 template <class I, class F>
792 Future<I> Future<T>::reduce(I&& initial, F&& func) {
793 folly::MoveWrapper<I> minitial(std::move(initial));
794 folly::MoveWrapper<F> mfunc(std::move(func));
795 return then([minitial, mfunc](T& vals) mutable {
796 auto ret = std::move(*minitial);
797 for (auto& val : vals) {
798 ret = (*mfunc)(std::move(ret), std::move(val));
804 template <class It, class T, class F, class ItT, class Arg>
805 Future<T> unorderedReduce(It first, It last, T initial, F func) {
807 return makeFuture(std::move(initial));
810 typedef isTry<Arg> IsTry;
812 struct UnorderedReduceContext {
813 UnorderedReduceContext(T&& memo, F&& fn, size_t n)
814 : lock_(), memo_(makeFuture<T>(std::move(memo))),
815 func_(std::move(fn)), numThens_(0), numFutures_(n), promise_()
817 folly::MicroSpinLock lock_; // protects memo_ and numThens_
820 size_t numThens_; // how many Futures completed and called .then()
821 size_t numFutures_; // how many Futures in total
825 auto ctx = std::make_shared<UnorderedReduceContext>(
826 std::move(initial), std::move(func), std::distance(first, last));
828 mapSetCallback<ItT>(first, last, [ctx](size_t i, Try<ItT>&& t) {
829 folly::MoveWrapper<Try<ItT>> mt(std::move(t));
830 // Futures can be completed in any order, simultaneously.
831 // To make this non-blocking, we create a new Future chain in
832 // the order of completion to reduce the values.
833 // The spinlock just protects chaining a new Future, not actually
834 // executing the reduce, which should be really fast.
835 folly::MSLGuard lock(ctx->lock_);
836 ctx->memo_ = ctx->memo_.then([ctx, mt](T&& v) mutable {
837 // Either return a ItT&& or a Try<ItT>&& depending
838 // on the type of the argument of func.
839 return ctx->func_(std::move(v), mt->template get<IsTry::value, Arg&&>());
841 if (++ctx->numThens_ == ctx->numFutures_) {
842 // After reducing the value of the last Future, fulfill the Promise
843 ctx->memo_.setCallback_([ctx](Try<T>&& t2) {
844 ctx->promise_.setValue(std::move(t2));
849 return ctx->promise_.getFuture();
853 Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
854 return within(dur, TimedOut(), tk);
859 Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
862 Context(E ex) : exception(std::move(ex)), promise(), token(false) {}
865 std::atomic<bool> token;
867 auto ctx = std::make_shared<Context>(std::move(e));
870 tk = folly::detail::getTimekeeperSingleton();
874 .then([ctx](Try<void> const& t) {
875 if (ctx->token.exchange(true) == false) {
876 if (t.hasException()) {
877 ctx->promise.setException(std::move(t.exception()));
879 ctx->promise.setException(std::move(ctx->exception));
884 this->then([ctx](Try<T>&& t) {
885 if (ctx->token.exchange(true) == false) {
886 ctx->promise.setTry(std::move(t));
890 return ctx->promise.getFuture().via(getExecutor());
894 Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
895 return collectAll(*this, futures::sleep(dur, tk))
896 .then([](std::tuple<Try<T>, Try<void>> tup) {
897 Try<T>& t = std::get<0>(tup);
898 return makeFuture<T>(std::move(t));
905 void waitImpl(Future<T>& f) {
906 // short-circuit if there's nothing to do
907 if (f.isReady()) return;
909 folly::fibers::Baton baton;
910 f = f.then([&](Try<T> t) {
912 return makeFuture(std::move(t));
916 // There's a race here between the return here and the actual finishing of
917 // the future. f is completed, but the setup may not have finished on done
918 // after the baton has posted.
919 while (!f.isReady()) {
920 std::this_thread::yield();
925 void waitImpl(Future<T>& f, Duration dur) {
926 // short-circuit if there's nothing to do
927 if (f.isReady()) return;
929 auto baton = std::make_shared<folly::fibers::Baton>();
930 f = f.then([baton](Try<T> t) {
932 return makeFuture(std::move(t));
935 // Let's preserve the invariant that if we did not timeout (timed_wait returns
936 // true), then the returned Future is complete when it is returned to the
937 // caller. We need to wait out the race for that Future to complete.
938 if (baton->timed_wait(dur)) {
939 while (!f.isReady()) {
940 std::this_thread::yield();
946 void waitViaImpl(Future<T>& f, DrivableExecutor* e) {
947 while (!f.isReady()) {
955 Future<T>& Future<T>::wait() & {
956 detail::waitImpl(*this);
961 Future<T>&& Future<T>::wait() && {
962 detail::waitImpl(*this);
963 return std::move(*this);
967 Future<T>& Future<T>::wait(Duration dur) & {
968 detail::waitImpl(*this, dur);
973 Future<T>&& Future<T>::wait(Duration dur) && {
974 detail::waitImpl(*this, dur);
975 return std::move(*this);
979 Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
980 detail::waitViaImpl(*this, e);
985 Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
986 detail::waitViaImpl(*this, e);
987 return std::move(*this);
992 return std::move(wait().value());
996 inline void Future<void>::get() {
1001 T Future<T>::get(Duration dur) {
1004 return std::move(value());
1011 inline void Future<void>::get(Duration dur) {
1021 T Future<T>::getVia(DrivableExecutor* e) {
1022 return std::move(waitVia(e).value());
1026 inline void Future<void>::getVia(DrivableExecutor* e) {
1033 static bool equals(const Try<T>& t1, const Try<T>& t2) {
1034 return t1.value() == t2.value();
1039 struct TryEquals<void> {
1040 static bool equals(const Try<void>& t1, const Try<void>& t2) {
1047 Future<bool> Future<T>::willEqual(Future<T>& f) {
1048 return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
1049 if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
1050 return detail::TryEquals<T>::equals(std::get<0>(t), std::get<1>(t));
1059 Future<T> Future<T>::filter(F predicate) {
1060 auto p = folly::makeMoveWrapper(std::move(predicate));
1061 return this->then([p](T val) {
1062 T const& valConstRef = val;
1063 if (!(*p)(valConstRef)) {
1064 throw PredicateDoesNotObtain();
1071 template <class Callback>
1072 auto Future<T>::thenMulti(Callback&& fn)
1073 -> decltype(this->then(std::forward<Callback>(fn))) {
1074 // thenMulti with one callback is just a then
1075 return then(std::forward<Callback>(fn));
1079 template <class Callback, class... Callbacks>
1080 auto Future<T>::thenMulti(Callback&& fn, Callbacks&&... fns)
1081 -> decltype(this->then(std::forward<Callback>(fn)).
1082 thenMulti(std::forward<Callbacks>(fns)...)) {
1083 // thenMulti with two callbacks is just then(a).thenMulti(b, ...)
1084 return then(std::forward<Callback>(fn)).
1085 thenMulti(std::forward<Callbacks>(fns)...);
1089 template <class Callback, class... Callbacks>
1090 auto Future<T>::thenMultiWithExecutor(Executor* x, Callback&& fn,
1092 -> decltype(this->then(std::forward<Callback>(fn)).
1093 thenMulti(std::forward<Callbacks>(fns)...)) {
1094 // thenMultiExecutor with two callbacks is
1095 // via(x).then(a).thenMulti(b, ...).via(oldX)
1096 auto oldX = getExecutor();
1098 return then(std::forward<Callback>(fn)).
1099 thenMulti(std::forward<Callbacks>(fns)...).via(oldX);
1103 template <class Callback>
1104 auto Future<T>::thenMultiWithExecutor(Executor* x, Callback&& fn)
1105 -> decltype(this->then(std::forward<Callback>(fn))) {
1106 // thenMulti with one callback is just a then with an executor
1107 return then(x, std::forward<Callback>(fn));
1111 template <class It, class F, class ItT, class Result>
1112 std::vector<Future<Result>> map(It first, It last, F func) {
1113 std::vector<Future<Result>> results;
1114 for (auto it = first; it != last; it++) {
1115 results.push_back(it->then(func));
1121 // Instantiate the most common Future types to save compile time
1122 extern template class Future<void>;
1123 extern template class Future<bool>;
1124 extern template class Future<int>;
1125 extern template class Future<int64_t>;
1126 extern template class Future<std::string>;
1127 extern template class Future<double>;
1129 } // namespace folly
1131 // I haven't included a Future<T&> specialization because I don't forsee us
1132 // using it, however it is not difficult to add when needed. Refer to
1133 // Future<void> for guidance. std::future and boost::future code would also be