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 bool Future<T>::isReady() const {
343 return core_->ready();
347 void Future<T>::raise(std::exception_ptr exception) {
348 core_->raise(exception);
354 Future<typename std::decay<T>::type> makeFuture(T&& t) {
355 Promise<typename std::decay<T>::type> p;
356 auto f = p.getFuture();
357 p.setValue(std::forward<T>(t));
361 inline // for multiple translation units
362 Future<void> makeFuture() {
364 auto f = p.getFuture();
372 typename std::enable_if<!std::is_reference<F>::value, bool>::type sdf)
373 -> Future<decltype(func())> {
374 Promise<decltype(func())> p;
375 auto f = p.getFuture();
384 auto makeFutureTry(F const& func) -> Future<decltype(func())> {
386 return makeFutureTry(std::move(copy));
390 Future<T> makeFuture(std::exception_ptr const& e) {
392 auto f = p.getFuture();
397 template <class T, class E>
398 typename std::enable_if<std::is_base_of<std::exception, E>::value,
400 makeFuture(E const& e) {
402 auto f = p.getFuture();
403 p.fulfil([&]() -> T { throw e; });
408 Future<T> makeFuture(Try<T>&& t) {
410 return makeFuture<T>(std::move(t.value()));
412 return makeFuture<T>(std::current_exception());
417 inline Future<void> makeFuture(Try<void>&& t) {
422 return makeFuture<void>(std::current_exception());
428 template <typename... Fs>
429 typename detail::VariadicContext<
430 typename std::decay<Fs>::type::value_type...>::type
434 new detail::VariadicContext<typename std::decay<Fs>::type::value_type...>();
435 ctx->total = sizeof...(fs);
436 auto f_saved = ctx->p.getFuture();
437 detail::whenAllVariadicHelper(ctx,
438 std::forward<typename std::decay<Fs>::type>(fs)...);
439 return std::move(f_saved);
444 template <class InputIterator>
447 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
448 whenAll(InputIterator first, InputIterator last)
451 typename std::iterator_traits<InputIterator>::value_type::value_type T;
453 auto n = std::distance(first, last);
455 return makeFuture(std::vector<Try<T>>());
458 auto ctx = new detail::WhenAllContext<T>();
461 ctx->results.resize(ctx->total);
463 auto f_saved = ctx->p.getFuture();
465 for (size_t i = 0; first != last; ++first, ++i) {
467 f.setCallback_([ctx, i](Try<T>&& t) {
468 ctx->results[i] = std::move(t);
469 if (++ctx->count == ctx->total) {
470 ctx->p.setValue(std::move(ctx->results));
476 return std::move(f_saved);
479 template <class InputIterator>
484 std::iterator_traits<InputIterator>::value_type::value_type> > >
485 whenAny(InputIterator first, InputIterator last) {
487 typename std::iterator_traits<InputIterator>::value_type::value_type T;
489 auto ctx = new detail::WhenAnyContext<T>(std::distance(first, last));
490 auto f_saved = ctx->p.getFuture();
492 for (size_t i = 0; first != last; first++, i++) {
494 f.setCallback_([i, ctx](Try<T>&& t) {
495 if (!ctx->done.exchange(true)) {
496 ctx->p.setValue(std::make_pair(i, std::move(t)));
502 return std::move(f_saved);
505 template <class InputIterator>
506 Future<std::vector<std::pair<size_t, Try<typename
507 std::iterator_traits<InputIterator>::value_type::value_type>>>>
508 whenN(InputIterator first, InputIterator last, size_t n) {
510 std::iterator_traits<InputIterator>::value_type::value_type T;
511 typedef std::vector<std::pair<size_t, Try<T>>> V;
518 auto ctx = std::make_shared<ctx_t>();
521 // for each completed Future, increase count and add to vector, until we
522 // have n completed futures at which point we fulfil our Promise with the
527 it->then([ctx, n, i](Try<T>&& t) {
529 auto c = ++ctx->completed;
531 assert(ctx->v.size() < n);
532 v.push_back(std::make_pair(i, std::move(t)));
534 ctx->p.fulfilTry(Try<V>(std::move(v)));
544 ctx->p.setException(std::runtime_error("Not enough futures"));
547 return ctx->p.getFuture();
550 template <typename T>
552 waitWithSemaphore(Future<T>&& f) {
554 auto done = f.then([&](Try<T> &&t) {
556 return std::move(t.value());
559 while (!done.isReady()) {
560 // There's a race here between the return here and the actual finishing of
561 // the future. f is completed, but the setup may not have finished on done
562 // after the baton has posted.
563 std::this_thread::yield();
569 inline Future<void> waitWithSemaphore<void>(Future<void>&& f) {
571 auto done = f.then([&](Try<void> &&t) {
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();
585 template <typename T, class Duration>
587 waitWithSemaphore(Future<T>&& f, Duration timeout) {
588 auto baton = std::make_shared<Baton<>>();
589 auto done = f.then([baton](Try<T> &&t) {
591 return std::move(t.value());
593 baton->timed_wait(std::chrono::system_clock::now() + timeout);
597 template <class Duration>
599 waitWithSemaphore(Future<void>&& f, Duration timeout) {
600 auto baton = std::make_shared<Baton<>>();
601 auto done = f.then([baton](Try<void> &&t) {
605 baton->timed_wait(std::chrono::system_clock::now() + timeout);
611 // I haven't included a Future<T&> specialization because I don't forsee us
612 // using it, however it is not difficult to add when needed. Refer to
613 // Future<void> for guidance. std::future and boost::future code would also be