2 * Copyright 2014 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/wangle/futures/detail/Core.h>
23 #include <folly/Baton.h>
25 namespace folly { namespace wangle {
29 static const bool value = false;
33 struct isFuture<Future<T> > {
34 static const bool value = true;
38 Future<T>::Future(Future<T>&& other) noexcept : core_(nullptr) {
39 *this = std::move(other);
43 Future<T>& Future<T>::operator=(Future<T>&& other) {
44 std::swap(core_, other.core_);
49 Future<T>::~Future() {
54 void Future<T>::detach() {
56 core_->detachFuture();
62 void Future<T>::throwIfInvalid() const {
69 void Future<T>::setCallback_(F&& func) {
71 core_->setCallback(std::move(func));
74 // Variant: f.then([](Try<T>&& t){ return t.value(); });
77 typename std::enable_if<
78 !isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
79 Future<typename std::result_of<F(Try<T>&&)>::type> >::type
80 Future<T>::then(F&& func) {
81 typedef typename std::result_of<F(Try<T>&&)>::type B;
85 // wrap these so we can move them into the lambda
86 folly::MoveWrapper<Promise<B>> p;
87 folly::MoveWrapper<F> funcm(std::forward<F>(func));
89 // grab the Future now before we lose our handle on the Promise
90 auto f = p->getFuture();
92 /* This is a bit tricky.
94 We can't just close over *this in case this Future gets moved. So we
95 make a new dummy Future. We could figure out something more
96 sophisticated that avoids making a new Future object when it can, as an
97 optimization. But this is correct.
99 core_ can't be moved, it is explicitly disallowed (as is copying). But
100 if there's ever a reason to allow it, this is one place that makes that
101 assumption and would need to be fixed. We use a standard shared pointer
102 for core_ (by copying it in), which means in essence obj holds a shared
103 pointer to itself. But this shouldn't leak because Promise will not
104 outlive the continuation, because Promise will setException() with a
105 broken Promise if it is destructed before completed. We could use a
106 weak pointer but it would have to be converted to a shared pointer when
107 func is executed (because the Future returned by func may possibly
108 persist beyond the callback, if it gets moved), and so it is an
109 optimization to just make it shared from the get-go.
111 We have to move in the Promise and func using the MoveWrapper
112 hack. (func could be copied but it's a big drag on perf).
114 Two subtle but important points about this design. detail::Core has no
115 back pointers to Future or Promise, so if Future or Promise get moved
116 (and they will be moved in performant code) we don't have to do
117 anything fancy. And because we store the continuation in the
118 detail::Core, not in the Future, we can execute the continuation even
119 after the Future has gone out of scope. This is an intentional design
120 decision. It is likely we will want to be able to cancel a continuation
121 in some circumstances, but I think it should be explicit not implicit
122 in the destruction of the Future used to create it.
125 [p, funcm](Try<T>&& t) mutable {
127 return (*funcm)(std::move(t));
134 // Variant: f.then([](T&& t){ return t; });
137 typename std::enable_if<
138 !std::is_same<T, void>::value &&
139 !isFuture<typename std::result_of<
140 F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
141 Future<typename std::result_of<
142 F(typename detail::AliasIfVoid<T>::type&&)>::type> >::type
143 Future<T>::then(F&& func) {
144 typedef typename std::result_of<F(T&&)>::type B;
148 folly::MoveWrapper<Promise<B>> p;
149 folly::MoveWrapper<F> funcm(std::forward<F>(func));
150 auto f = p->getFuture();
153 [p, funcm](Try<T>&& t) mutable {
154 if (t.hasException()) {
155 p->setException(t.getException());
158 return (*funcm)(std::move(t.value()));
166 // Variant: f.then([](){ return; });
169 typename std::enable_if<
170 std::is_same<T, void>::value &&
171 !isFuture<typename std::result_of<F()>::type>::value,
172 Future<typename std::result_of<F()>::type> >::type
173 Future<T>::then(F&& func) {
174 typedef typename std::result_of<F()>::type B;
178 folly::MoveWrapper<Promise<B>> p;
179 folly::MoveWrapper<F> funcm(std::forward<F>(func));
180 auto f = p->getFuture();
183 [p, funcm](Try<T>&& t) mutable {
184 if (t.hasException()) {
185 p->setException(t.getException());
196 // Variant: f.then([](Try<T>&& t){ return makeFuture<T>(t.value()); });
199 typename std::enable_if<
200 isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
201 Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
202 Future<T>::then(F&& func) {
203 typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
207 // wrap these so we can move them into the lambda
208 folly::MoveWrapper<Promise<B>> p;
209 folly::MoveWrapper<F> funcm(std::forward<F>(func));
211 // grab the Future now before we lose our handle on the Promise
212 auto f = p->getFuture();
215 [p, funcm](Try<T>&& t) mutable {
217 auto f2 = (*funcm)(std::move(t));
218 // that didn't throw, now we can steal p
219 f2.setCallback_([p](Try<B>&& b) mutable {
220 p->fulfilTry(std::move(b));
223 p->setException(std::current_exception());
230 // Variant: f.then([](T&& t){ return makeFuture<T>(t); });
233 typename std::enable_if<
234 !std::is_same<T, void>::value &&
235 isFuture<typename std::result_of<
236 F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
237 Future<typename std::result_of<
238 F(typename detail::AliasIfVoid<T>::type&&)>::type::value_type> >::type
239 Future<T>::then(F&& func) {
240 typedef typename std::result_of<F(T&&)>::type::value_type B;
244 folly::MoveWrapper<Promise<B>> p;
245 folly::MoveWrapper<F> funcm(std::forward<F>(func));
246 auto f = p->getFuture();
249 [p, funcm](Try<T>&& t) mutable {
250 if (t.hasException()) {
251 p->setException(t.getException());
254 auto f2 = (*funcm)(std::move(t.value()));
255 f2.setCallback_([p](Try<B>&& b) mutable {
256 p->fulfilTry(std::move(b));
259 p->setException(std::current_exception());
267 // Variant: f.then([](){ return makeFuture(); });
270 typename std::enable_if<
271 std::is_same<T, void>::value &&
272 isFuture<typename std::result_of<F()>::type>::value,
273 Future<typename std::result_of<F()>::type::value_type> >::type
274 Future<T>::then(F&& func) {
275 typedef typename std::result_of<F()>::type::value_type B;
279 folly::MoveWrapper<Promise<B>> p;
280 folly::MoveWrapper<F> funcm(std::forward<F>(func));
282 auto f = p->getFuture();
285 [p, funcm](Try<T>&& t) mutable {
286 if (t.hasException()) {
287 p->setException(t.getException());
290 auto f2 = (*funcm)();
291 f2.setCallback_([p](Try<B>&& b) mutable {
292 p->fulfilTry(std::move(b));
295 p->setException(std::current_exception());
304 Future<void> Future<T>::then() {
305 return then([] (Try<T>&& t) {});
308 // onError where the callback returns T
311 typename std::enable_if<
312 !detail::Extract<F>::ReturnsFuture::value,
314 Future<T>::onError(F&& func) {
315 typedef typename detail::Extract<F>::FirstArg Exn;
317 std::is_same<typename detail::Extract<F>::RawReturn, T>::value,
318 "Return type of onError callback must be T or Future<T>");
321 auto f = p.getFuture();
322 auto pm = folly::makeMoveWrapper(std::move(p));
323 auto funcm = folly::makeMoveWrapper(std::move(func));
324 setCallback_([pm, funcm](Try<T>&& t) mutable {
335 pm->fulfilTry(std::move(t));
341 // onError where the callback returns Future<T>
344 typename std::enable_if<
345 detail::Extract<F>::ReturnsFuture::value,
347 Future<T>::onError(F&& func) {
349 std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
350 "Return type of onError callback must be T or Future<T>");
351 typedef typename detail::Extract<F>::FirstArg Exn;
354 auto f = p.getFuture();
355 auto pm = folly::makeMoveWrapper(std::move(p));
356 auto funcm = folly::makeMoveWrapper(std::move(func));
357 setCallback_([pm, funcm](Try<T>&& t) mutable {
362 auto f2 = (*funcm)(e);
363 f2.setCallback_([pm](Try<T>&& t2) mutable {
364 pm->fulfilTry(std::move(t2));
367 pm->setException(std::current_exception());
373 pm->fulfilTry(std::move(t));
380 typename std::add_lvalue_reference<T>::type Future<T>::value() {
383 return core_->getTry().value();
387 typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
390 return core_->getTry().value();
394 Try<T>& Future<T>::getTry() {
397 return core_->getTry();
401 template <typename Executor>
402 inline Future<T> Future<T>::via(Executor* executor) && {
406 core_->setExecutor(executor);
408 return std::move(*this);
412 template <typename Executor>
413 inline Future<T> Future<T>::via(Executor* executor) & {
416 MoveWrapper<Promise<T>> p;
417 auto f = p->getFuture();
418 then([p](Try<T>&& t) mutable { p->fulfilTry(std::move(t)); });
419 return std::move(f).via(executor);
423 bool Future<T>::isReady() const {
425 return core_->ready();
429 void Future<T>::raise(std::exception_ptr exception) {
430 core_->raise(exception);
436 Future<typename std::decay<T>::type> makeFuture(T&& t) {
437 Promise<typename std::decay<T>::type> p;
438 auto f = p.getFuture();
439 p.setValue(std::forward<T>(t));
443 inline // for multiple translation units
444 Future<void> makeFuture() {
446 auto f = p.getFuture();
454 typename std::enable_if<!std::is_reference<F>::value, bool>::type sdf)
455 -> Future<decltype(func())> {
456 Promise<decltype(func())> p;
457 auto f = p.getFuture();
466 auto makeFutureTry(F const& func) -> Future<decltype(func())> {
468 return makeFutureTry(std::move(copy));
472 Future<T> makeFuture(std::exception_ptr const& e) {
474 auto f = p.getFuture();
479 template <class T, class E>
480 typename std::enable_if<std::is_base_of<std::exception, E>::value,
482 makeFuture(E const& e) {
484 auto f = p.getFuture();
485 p.fulfil([&]() -> T { throw e; });
490 Future<T> makeFuture(Try<T>&& t) {
492 return makeFuture<T>(std::move(t.value()));
494 return makeFuture<T>(std::current_exception());
499 inline Future<void> makeFuture(Try<void>&& t) {
504 return makeFuture<void>(std::current_exception());
509 template <typename Executor>
510 Future<void> via(Executor* executor) {
511 return makeFuture().via(executor);
516 template <typename... Fs>
517 typename detail::VariadicContext<
518 typename std::decay<Fs>::type::value_type...>::type
522 new detail::VariadicContext<typename std::decay<Fs>::type::value_type...>();
523 ctx->total = sizeof...(fs);
524 auto f_saved = ctx->p.getFuture();
525 detail::whenAllVariadicHelper(ctx,
526 std::forward<typename std::decay<Fs>::type>(fs)...);
527 return std::move(f_saved);
532 template <class InputIterator>
535 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
536 whenAll(InputIterator first, InputIterator last)
539 typename std::iterator_traits<InputIterator>::value_type::value_type T;
541 auto n = std::distance(first, last);
543 return makeFuture(std::vector<Try<T>>());
546 auto ctx = new detail::WhenAllContext<T>();
548 ctx->results.resize(n);
550 auto f_saved = ctx->p.getFuture();
552 for (size_t i = 0; first != last; ++first, ++i) {
555 f.setCallback_([ctx, i, n](Try<T>&& t) {
556 ctx->results[i] = std::move(t);
557 if (++ctx->count == n) {
558 ctx->p.setValue(std::move(ctx->results));
564 return std::move(f_saved);
567 template <class InputIterator>
572 std::iterator_traits<InputIterator>::value_type::value_type> > >
573 whenAny(InputIterator first, InputIterator last) {
575 typename std::iterator_traits<InputIterator>::value_type::value_type T;
577 auto ctx = new detail::WhenAnyContext<T>(std::distance(first, last));
578 auto f_saved = ctx->p.getFuture();
580 for (size_t i = 0; first != last; first++, i++) {
582 f.setCallback_([i, ctx](Try<T>&& t) {
583 if (!ctx->done.exchange(true)) {
584 ctx->p.setValue(std::make_pair(i, std::move(t)));
590 return std::move(f_saved);
593 template <class InputIterator>
594 Future<std::vector<std::pair<size_t, Try<typename
595 std::iterator_traits<InputIterator>::value_type::value_type>>>>
596 whenN(InputIterator first, InputIterator last, size_t n) {
598 std::iterator_traits<InputIterator>::value_type::value_type T;
599 typedef std::vector<std::pair<size_t, Try<T>>> V;
606 auto ctx = std::make_shared<ctx_t>();
609 // for each completed Future, increase count and add to vector, until we
610 // have n completed futures at which point we fulfil our Promise with the
615 it->then([ctx, n, i](Try<T>&& t) {
617 auto c = ++ctx->completed;
619 assert(ctx->v.size() < n);
620 v.push_back(std::make_pair(i, std::move(t)));
622 ctx->p.fulfilTry(Try<V>(std::move(v)));
632 ctx->p.setException(std::runtime_error("Not enough futures"));
635 return ctx->p.getFuture();
638 template <typename T>
640 waitWithSemaphore(Future<T>&& f) {
642 auto done = f.then([&](Try<T> &&t) {
644 return std::move(t.value());
647 while (!done.isReady()) {
648 // There's a race here between the return here and the actual finishing of
649 // the future. f is completed, but the setup may not have finished on done
650 // after the baton has posted.
651 std::this_thread::yield();
657 inline Future<void> waitWithSemaphore<void>(Future<void>&& f) {
659 auto done = f.then([&](Try<void> &&t) {
664 while (!done.isReady()) {
665 // There's a race here between the return here and the actual finishing of
666 // the future. f is completed, but the setup may not have finished on done
667 // after the baton has posted.
668 std::this_thread::yield();
673 template <typename T, class Duration>
675 waitWithSemaphore(Future<T>&& f, Duration timeout) {
676 auto baton = std::make_shared<Baton<>>();
677 auto done = f.then([baton](Try<T> &&t) {
679 return std::move(t.value());
681 baton->timed_wait(std::chrono::system_clock::now() + timeout);
685 template <class Duration>
687 waitWithSemaphore(Future<void>&& f, Duration timeout) {
688 auto baton = std::make_shared<Baton<>>();
689 auto done = f.then([baton](Try<void> &&t) {
693 baton->timed_wait(std::chrono::system_clock::now() + timeout);
699 // I haven't included a Future<T&> specialization because I don't forsee us
700 // using it, however it is not difficult to add when needed. Refer to
701 // Future<void> for guidance. std::future and boost::future code would also be