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<ItT>&& 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));
804 Future<T> Future<T>::within(Duration dur, Timekeeper* tk) {
805 return within(dur, TimedOut(), tk);
810 Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
813 Context(E ex) : exception(std::move(ex)), promise(), token(false) {}
816 std::atomic<bool> token;
818 auto ctx = std::make_shared<Context>(std::move(e));
821 tk = folly::detail::getTimekeeperSingleton();
825 .then([ctx](Try<void> const& t) {
826 if (ctx->token.exchange(true) == false) {
827 if (t.hasException()) {
828 ctx->promise.setException(std::move(t.exception()));
830 ctx->promise.setException(std::move(ctx->exception));
835 this->then([ctx](Try<T>&& t) {
836 if (ctx->token.exchange(true) == false) {
837 ctx->promise.setTry(std::move(t));
841 return ctx->promise.getFuture();
845 Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
846 return collectAll(*this, futures::sleep(dur, tk))
847 .then([](std::tuple<Try<T>, Try<void>> tup) {
848 Try<T>& t = std::get<0>(tup);
849 return makeFuture<T>(std::move(t));
856 void waitImpl(Future<T>& f) {
857 // short-circuit if there's nothing to do
858 if (f.isReady()) return;
860 folly::fibers::Baton baton;
861 f = f.then([&](Try<T> t) {
863 return makeFuture(std::move(t));
867 // There's a race here between the return here and the actual finishing of
868 // the future. f is completed, but the setup may not have finished on done
869 // after the baton has posted.
870 while (!f.isReady()) {
871 std::this_thread::yield();
876 void waitImpl(Future<T>& f, Duration dur) {
877 // short-circuit if there's nothing to do
878 if (f.isReady()) return;
880 auto baton = std::make_shared<folly::fibers::Baton>();
881 f = f.then([baton](Try<T> t) {
883 return makeFuture(std::move(t));
886 // Let's preserve the invariant that if we did not timeout (timed_wait returns
887 // true), then the returned Future is complete when it is returned to the
888 // caller. We need to wait out the race for that Future to complete.
889 if (baton->timed_wait(dur)) {
890 while (!f.isReady()) {
891 std::this_thread::yield();
897 void waitViaImpl(Future<T>& f, DrivableExecutor* e) {
898 while (!f.isReady()) {
906 Future<T>& Future<T>::wait() & {
907 detail::waitImpl(*this);
912 Future<T>&& Future<T>::wait() && {
913 detail::waitImpl(*this);
914 return std::move(*this);
918 Future<T>& Future<T>::wait(Duration dur) & {
919 detail::waitImpl(*this, dur);
924 Future<T>&& Future<T>::wait(Duration dur) && {
925 detail::waitImpl(*this, dur);
926 return std::move(*this);
930 Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
931 detail::waitViaImpl(*this, e);
936 Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
937 detail::waitViaImpl(*this, e);
938 return std::move(*this);
943 return std::move(wait().value());
947 inline void Future<void>::get() {
952 T Future<T>::get(Duration dur) {
955 return std::move(value());
962 inline void Future<void>::get(Duration dur) {
972 T Future<T>::getVia(DrivableExecutor* e) {
973 return std::move(waitVia(e).value());
977 inline void Future<void>::getVia(DrivableExecutor* e) {
984 static bool equals(const Try<T>& t1, const Try<T>& t2) {
985 return t1.value() == t2.value();
990 struct TryEquals<void> {
991 static bool equals(const Try<void>& t1, const Try<void>& t2) {
998 Future<bool> Future<T>::willEqual(Future<T>& f) {
999 return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
1000 if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
1001 return detail::TryEquals<T>::equals(std::get<0>(t), std::get<1>(t));
1010 Future<T> Future<T>::filter(F predicate) {
1011 auto p = folly::makeMoveWrapper(std::move(predicate));
1012 return this->then([p](T val) {
1013 T const& valConstRef = val;
1014 if (!(*p)(valConstRef)) {
1015 throw PredicateDoesNotObtain();
1024 Future<Z> chainHelper(Future<Z> f) {
1028 template <class Z, class F, class Fn, class... Callbacks>
1029 Future<Z> chainHelper(F f, Fn fn, Callbacks... fns) {
1030 return chainHelper<Z>(f.then(fn), fns...);
1034 template <class A, class Z, class... Callbacks>
1035 std::function<Future<Z>(Try<A>)>
1036 chain(Callbacks... fns) {
1037 MoveWrapper<Promise<A>> pw;
1038 MoveWrapper<Future<Z>> fw(chainHelper<Z>(pw->getFuture(), fns...));
1039 return [=](Try<A> t) mutable {
1040 pw->setTry(std::move(t));
1041 return std::move(*fw);
1045 template <class It, class F, class ItT, class Result>
1046 std::vector<Future<Result>> map(It first, It last, F func) {
1047 std::vector<Future<Result>> results;
1048 for (auto it = first; it != last; it++) {
1049 results.push_back(it->then(func));
1055 // Instantiate the most common Future types to save compile time
1056 extern template class Future<void>;
1057 extern template class Future<bool>;
1058 extern template class Future<int>;
1059 extern template class Future<int64_t>;
1060 extern template class Future<std::string>;
1061 extern template class Future<double>;
1063 } // namespace folly
1065 // I haven't included a Future<T&> specialization because I don't forsee us
1066 // using it, however it is not difficult to add when needed. Refer to
1067 // Future<void> for guidance. std::future and boost::future code would also be