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/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) {});
309 typename std::add_lvalue_reference<T>::type Future<T>::value() {
312 return core_->getTry().value();
316 typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
319 return core_->getTry().value();
323 Try<T>& Future<T>::getTry() {
326 return core_->getTry();
330 template <typename Executor>
331 inline Future<T> Future<T>::via(Executor* executor) && {
335 core_->setExecutor(executor);
337 return std::move(*this);
341 template <typename Executor>
342 inline Future<T> Future<T>::via(Executor* executor) & {
345 MoveWrapper<Promise<T>> p;
346 auto f = p->getFuture();
347 then([p](Try<T>&& t) mutable { p->fulfilTry(std::move(t)); });
348 return std::move(f).via(executor);
352 bool Future<T>::isReady() const {
354 return core_->ready();
358 void Future<T>::raise(std::exception_ptr exception) {
359 core_->raise(exception);
365 Future<typename std::decay<T>::type> makeFuture(T&& t) {
366 Promise<typename std::decay<T>::type> p;
367 auto f = p.getFuture();
368 p.setValue(std::forward<T>(t));
372 inline // for multiple translation units
373 Future<void> makeFuture() {
375 auto f = p.getFuture();
383 typename std::enable_if<!std::is_reference<F>::value, bool>::type sdf)
384 -> Future<decltype(func())> {
385 Promise<decltype(func())> p;
386 auto f = p.getFuture();
395 auto makeFutureTry(F const& func) -> Future<decltype(func())> {
397 return makeFutureTry(std::move(copy));
401 Future<T> makeFuture(std::exception_ptr const& e) {
403 auto f = p.getFuture();
408 template <class T, class E>
409 typename std::enable_if<std::is_base_of<std::exception, E>::value,
411 makeFuture(E const& e) {
413 auto f = p.getFuture();
414 p.fulfil([&]() -> T { throw e; });
419 Future<T> makeFuture(Try<T>&& t) {
421 return makeFuture<T>(std::move(t.value()));
423 return makeFuture<T>(std::current_exception());
428 inline Future<void> makeFuture(Try<void>&& t) {
433 return makeFuture<void>(std::current_exception());
438 template <typename Executor>
439 Future<void> via(Executor* executor) {
440 return makeFuture().via(executor);
445 template <typename... Fs>
446 typename detail::VariadicContext<
447 typename std::decay<Fs>::type::value_type...>::type
451 new detail::VariadicContext<typename std::decay<Fs>::type::value_type...>();
452 ctx->total = sizeof...(fs);
453 auto f_saved = ctx->p.getFuture();
454 detail::whenAllVariadicHelper(ctx,
455 std::forward<typename std::decay<Fs>::type>(fs)...);
456 return std::move(f_saved);
461 template <class InputIterator>
464 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
465 whenAll(InputIterator first, InputIterator last)
468 typename std::iterator_traits<InputIterator>::value_type::value_type T;
470 auto n = std::distance(first, last);
472 return makeFuture(std::vector<Try<T>>());
475 auto ctx = new detail::WhenAllContext<T>();
477 ctx->results.resize(n);
479 auto f_saved = ctx->p.getFuture();
481 for (size_t i = 0; first != last; ++first, ++i) {
484 f.setCallback_([ctx, i, n](Try<T>&& t) {
485 ctx->results[i] = std::move(t);
486 if (++ctx->count == n) {
487 ctx->p.setValue(std::move(ctx->results));
493 return std::move(f_saved);
496 template <class InputIterator>
501 std::iterator_traits<InputIterator>::value_type::value_type> > >
502 whenAny(InputIterator first, InputIterator last) {
504 typename std::iterator_traits<InputIterator>::value_type::value_type T;
506 auto ctx = new detail::WhenAnyContext<T>(std::distance(first, last));
507 auto f_saved = ctx->p.getFuture();
509 for (size_t i = 0; first != last; first++, i++) {
511 f.setCallback_([i, ctx](Try<T>&& t) {
512 if (!ctx->done.exchange(true)) {
513 ctx->p.setValue(std::make_pair(i, std::move(t)));
519 return std::move(f_saved);
522 template <class InputIterator>
523 Future<std::vector<std::pair<size_t, Try<typename
524 std::iterator_traits<InputIterator>::value_type::value_type>>>>
525 whenN(InputIterator first, InputIterator last, size_t n) {
527 std::iterator_traits<InputIterator>::value_type::value_type T;
528 typedef std::vector<std::pair<size_t, Try<T>>> V;
535 auto ctx = std::make_shared<ctx_t>();
538 // for each completed Future, increase count and add to vector, until we
539 // have n completed futures at which point we fulfil our Promise with the
544 it->then([ctx, n, i](Try<T>&& t) {
546 auto c = ++ctx->completed;
548 assert(ctx->v.size() < n);
549 v.push_back(std::make_pair(i, std::move(t)));
551 ctx->p.fulfilTry(Try<V>(std::move(v)));
561 ctx->p.setException(std::runtime_error("Not enough futures"));
564 return ctx->p.getFuture();
567 template <typename T>
569 waitWithSemaphore(Future<T>&& f) {
571 auto done = f.then([&](Try<T> &&t) {
573 return std::move(t.value());
576 while (!done.isReady()) {
577 // There's a race here between the return here and the actual finishing of
578 // the future. f is completed, but the setup may not have finished on done
579 // after the baton has posted.
580 std::this_thread::yield();
586 inline Future<void> waitWithSemaphore<void>(Future<void>&& f) {
588 auto done = f.then([&](Try<void> &&t) {
593 while (!done.isReady()) {
594 // There's a race here between the return here and the actual finishing of
595 // the future. f is completed, but the setup may not have finished on done
596 // after the baton has posted.
597 std::this_thread::yield();
602 template <typename T, class Duration>
604 waitWithSemaphore(Future<T>&& f, Duration timeout) {
605 auto baton = std::make_shared<Baton<>>();
606 auto done = f.then([baton](Try<T> &&t) {
608 return std::move(t.value());
610 baton->timed_wait(std::chrono::system_clock::now() + timeout);
614 template <class Duration>
616 waitWithSemaphore(Future<void>&& f, Duration timeout) {
617 auto baton = std::make_shared<Baton<>>();
618 auto done = f.then([baton](Try<void> &&t) {
622 baton->timed_wait(std::chrono::system_clock::now() + timeout);
628 // I haven't included a Future<T&> specialization because I don't forsee us
629 // using it, however it is not difficult to add when needed. Refer to
630 // Future<void> for guidance. std::future and boost::future code would also be