| /* |
| * Copyright 2015 Facebook, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <algorithm> |
| #include <exception> |
| #include <functional> |
| #include <memory> |
| #include <type_traits> |
| #include <vector> |
| |
| #include <folly/Cancellation.h> |
| #include <folly/Optional.h> |
| #include <folly/Portability.h> |
| #include <folly/MoveWrapper.h> |
| #include <folly/futures/DrivableExecutor.h> |
| #include <folly/futures/Promise.h> |
| #include <folly/futures/Try.h> |
| #include <folly/futures/FutureException.h> |
| #include <folly/futures/detail/Types.h> |
| |
| // boring predeclarations and details |
| #include <folly/futures/Future-pre.h> |
| |
| // not-boring helpers, e.g. all in folly::futures, makeFuture variants, etc. |
| // Needs to be included after Future-pre.h and before Future-inl.h |
| #include <folly/futures/helpers.h> |
| |
| namespace folly { |
| |
| class Cancellation; |
| class ExecutorWithCancellation; |
| |
| template<class T> |
| struct has_cancellation { |
| protected: |
| static constexpr std::false_type detect(...); |
| template <class U> static decltype(std::declval<U>().getCancellation()) detect(const U&); |
| public: |
| static constexpr bool value = std::is_same<Cancellation&, decltype(detect(std::declval<T>()))>::value; |
| }; |
| |
| template <class T> |
| class Future { |
| public: |
| typedef T value_type; |
| |
| // not copyable |
| Future(Future const&) = delete; |
| Future& operator=(Future const&) = delete; |
| |
| // movable |
| Future(Future&&) noexcept; |
| Future& operator=(Future&&) noexcept; |
| |
| /// Construct a Future from a value (perfect forwarding) |
| template <class T2 = T, typename = |
| typename std::enable_if< |
| !isFuture<typename std::decay<T2>::type>::value>::type> |
| /* implicit */ Future(T2&& val); |
| |
| template <class T2 = T, typename = |
| typename std::enable_if< |
| std::is_same<Unit, T2>::value>::type> |
| Future(); |
| |
| ~Future(); |
| |
| /** Return the reference to result. Should not be called if !isReady(). |
| Will rethrow the exception if an exception has been |
| captured. |
| */ |
| typename std::add_lvalue_reference<T>::type |
| value(); |
| typename std::add_lvalue_reference<const T>::type |
| value() const; |
| |
| /// Returns an inactive Future which will call back on the other side of |
| /// executor (when it is activated). |
| /// |
| /// NB remember that Futures activate when they destruct. This is good, |
| /// it means that this will work: |
| /// |
| /// f.via(e).then(a).then(b); |
| /// |
| /// a and b will execute in the same context (the far side of e), because |
| /// the Future (temporary variable) created by via(e) does not call back |
| /// until it destructs, which is after then(a) and then(b) have been wired |
| /// up. |
| /// |
| /// But this is still racy: |
| /// |
| /// f = f.via(e).then(a); |
| /// f.then(b); |
| // The ref-qualifier allows for `this` to be moved out so we |
| // don't get access-after-free situations in chaining. |
| // https://akrzemi1.wordpress.com/2014/06/02/ref-qualifiers/ |
| inline Future<T> via( |
| Executor* executor, |
| int8_t priority = Executor::MID_PRI) &&; |
| |
| /// This variant creates a new future, where the ref-qualifier && version |
| /// moves `this` out. This one is less efficient but avoids confusing users |
| /// when "return f.via(x);" fails. |
| inline Future<T> via( |
| Executor* executor, |
| int8_t priority = Executor::MID_PRI) &; |
| |
| inline Future<T> via( |
| Executor* executor, |
| const Cancellation& cx, |
| int8_t priority = Executor::MID_PRI) &&; |
| |
| inline Future<T> via( |
| Executor* executor, |
| const Cancellation& cx, |
| int8_t priority = Executor::MID_PRI) &; |
| |
| inline Future<T> via( |
| ExecutorWithCancellation* executor, |
| int8_t priority = Executor::MID_PRI) &&; |
| |
| inline Future<T> via( |
| ExecutorWithCancellation* executor, |
| int8_t priority = Executor::MID_PRI) &; |
| |
| /** True when the result (or exception) is ready. */ |
| bool isReady() const; |
| |
| /// sugar for getTry().hasValue() |
| bool hasValue(); |
| |
| /// sugar for getTry().hasException() |
| bool hasException(); |
| |
| /** A reference to the Try of the value */ |
| Try<T>& getTry(); |
| |
| /// If the promise has been fulfilled, return an Optional with the Try<T>. |
| /// Otherwise return an empty Optional. |
| /// Note that this moves the Try<T> out. |
| Optional<Try<T>> poll(); |
| |
| /// Block until the future is fulfilled. Returns the value (moved out), or |
| /// throws the exception. The future must not already have a callback. |
| T get(); |
| |
| /// Block until the future is fulfilled, or until timed out. Returns the |
| /// value (moved out), or throws the exception (which might be a TimedOut |
| /// exception). |
| T get(Duration dur); |
| |
| /// Call e->drive() repeatedly until the future is fulfilled. Examples |
| /// of DrivableExecutor include EventBase and ManualExecutor. Returns the |
| /// value (moved out), or throws the exception. |
| T getVia(DrivableExecutor* e); |
| |
| /// Unwraps the case of a Future<Future<T>> instance, and returns a simple |
| /// Future<T> instance. |
| template <class F = T> |
| typename std::enable_if<isFuture<F>::value, |
| Future<typename isFuture<T>::Inner>>::type |
| unwrap(); |
| |
| /** When this Future has completed, execute func which is a function that |
| takes one of: |
| (const) Try<T>&& |
| (const) Try<T>& |
| (const) Try<T> |
| (const) T&& |
| (const) T& |
| (const) T |
| (void) |
| |
| Func shall return either another Future or a value. |
| |
| A Future for the return type of func is returned. |
| |
| Future<string> f2 = f1.then([](Try<T>&&) { return string("foo"); }); |
| |
| The Future given to the functor is ready, and the functor may call |
| value(), which may rethrow if this has captured an exception. If func |
| throws, the exception will be captured in the Future that is returned. |
| */ |
| template <typename F, typename R = detail::callableResult<T, F>> |
| typename R::Return then(F func) { |
| typedef typename R::Arg Arguments; |
| return thenImplementation<F, R>(std::move(func), Arguments()); |
| } |
| |
| /// Variant where func is an member function |
| /// |
| /// struct Worker { R doWork(Try<T>); } |
| /// |
| /// Worker *w; |
| /// Future<R> f2 = f1.then(&Worker::doWork, w); |
| /// |
| /// This is just sugar for |
| /// |
| /// f1.then(std::bind(&Worker::doWork, w)); |
| template <typename R, typename Caller, typename... Args> |
| Future<typename isFuture<R>::Inner> |
| then(R(Caller::*func)(Args...), Caller *instance); |
| |
| /// Execute the callback via the given Executor. The executor doesn't stick. |
| /// |
| /// Contrast |
| /// |
| /// f.via(x).then(b).then(c) |
| /// |
| /// with |
| /// |
| /// f.then(x, b).then(c) |
| /// |
| /// In the former both b and c execute via x. In the latter, only b executes |
| /// via x, and c executes via the same executor (if any) that f had. |
| template <class Executor, class Arg, class... Args> |
| auto then(Executor* x, Arg&& arg, Args&&... args) |
| -> typename std::enable_if<!has_cancellation<Executor>::value, |
| decltype(this->then(std::forward<Arg>(arg), |
| std::forward<Args>(args)...))>::type; |
| |
| template <class Executor, class Arg, class... Args> |
| auto then(Executor* x, Arg&& arg, Args&&... args) |
| -> typename std::enable_if<has_cancellation<Executor>::value, |
| decltype(this->then(std::forward<Arg>(arg), |
| std::forward<Args>(args)...))>::type; |
| /// Execute the callback via the given Executor with Cancellation. The executor doesn't stick. |
| /// |
| /// Contrast |
| /// |
| /// f.via(x, cx).then(b) |
| /// |
| /// with |
| /// |
| /// f.then(x, cx, b) |
| /// |
| /// In the former both b and c execute via x. In the latter, only b executes |
| /// via x, and c executes via the same executor (if any) that f had. |
| template <class Executor, class Arg, class... Args> |
| auto then(Executor* x, const Cancellation &cx, Arg&& arg, Args&&... args) |
| -> decltype(this->then(std::forward<Arg>(arg), |
| std::forward<Args>(args)...)); |
| |
| /// Convenience method for ignoring the value and creating a Future<Unit>. |
| /// Exceptions still propagate. |
| Future<Unit> then(); |
| |
| /// Set an error callback for this Future. The callback should take a single |
| /// argument of the type that you want to catch, and should return a value of |
| /// the same type as this Future, or a Future of that type (see overload |
| /// below). For instance, |
| /// |
| /// makeFuture() |
| /// .then([] { |
| /// throw std::runtime_error("oh no!"); |
| /// return 42; |
| /// }) |
| /// .onError([] (std::runtime_error& e) { |
| /// LOG(INFO) << "std::runtime_error: " << e.what(); |
| /// return -1; // or makeFuture<int>(-1) |
| /// }); |
| template <class F> |
| typename std::enable_if< |
| !detail::callableWith<F, exception_wrapper>::value && |
| !detail::Extract<F>::ReturnsFuture::value, |
| Future<T>>::type |
| onError(F&& func); |
| |
| /// Overload of onError where the error callback returns a Future<T> |
| template <class F> |
| typename std::enable_if< |
| !detail::callableWith<F, exception_wrapper>::value && |
| detail::Extract<F>::ReturnsFuture::value, |
| Future<T>>::type |
| onError(F&& func); |
| |
| /// Overload of onError that takes exception_wrapper and returns Future<T> |
| template <class F> |
| typename std::enable_if< |
| detail::callableWith<F, exception_wrapper>::value && |
| detail::Extract<F>::ReturnsFuture::value, |
| Future<T>>::type |
| onError(F&& func); |
| |
| /// Overload of onError that takes exception_wrapper and returns T |
| template <class F> |
| typename std::enable_if< |
| detail::callableWith<F, exception_wrapper>::value && |
| !detail::Extract<F>::ReturnsFuture::value, |
| Future<T>>::type |
| onError(F&& func); |
| |
| /// Convenience function to allow exceptions to throw in Executor |
| void onErrorThrowIn(Executor *x); |
| |
| /// func is like std::function<void()> and is executed unconditionally, and |
| /// the value/exception is passed through to the resulting Future. |
| /// func shouldn't throw, but if it does it will be captured and propagated, |
| /// and discard any value/exception that this Future has obtained. |
| template <class F> |
| Future<T> ensure(F func); |
| |
| /// Like onError, but for timeouts. example: |
| /// |
| /// Future<int> f = makeFuture<int>(42) |
| /// .delayed(long_time) |
| /// .onTimeout(short_time, |
| /// []() -> int{ return -1; }); |
| /// |
| /// or perhaps |
| /// |
| /// Future<int> f = makeFuture<int>(42) |
| /// .delayed(long_time) |
| /// .onTimeout(short_time, |
| /// []() { return makeFuture<int>(some_exception); }); |
| template <class F> |
| Future<T> onTimeout(Duration, F&& func, Timekeeper* = nullptr); |
| |
| /// This is not the method you're looking for. |
| /// |
| /// This needs to be public because it's used by make* and when*, and it's |
| /// not worth listing all those and their fancy template signatures as |
| /// friends. But it's not for public consumption. |
| template <class F> |
| void setCallback_(F&& func); |
| |
| /// A Future's callback is executed when all three of these conditions have |
| /// become true: it has a value (set by the Promise), it has a callback (set |
| /// by then), and it is active (active by default). |
| /// |
| /// Inactive Futures will activate upon destruction. |
| FOLLY_DEPRECATED("do not use") Future<T>& activate() & { |
| core_->activate(); |
| return *this; |
| } |
| FOLLY_DEPRECATED("do not use") Future<T>& deactivate() & { |
| core_->deactivate(); |
| return *this; |
| } |
| FOLLY_DEPRECATED("do not use") Future<T> activate() && { |
| core_->activate(); |
| return std::move(*this); |
| } |
| FOLLY_DEPRECATED("do not use") Future<T> deactivate() && { |
| core_->deactivate(); |
| return std::move(*this); |
| } |
| |
| bool isActive() { |
| return core_->isActive(); |
| } |
| |
| template <class E> |
| void raise(E&& exception) { |
| raise(make_exception_wrapper<typename std::remove_reference<E>::type>( |
| std::move(exception))); |
| } |
| |
| /// Raise an interrupt. If the promise holder has an interrupt |
| /// handler it will be called and potentially stop asynchronous work from |
| /// being done. This is advisory only - a promise holder may not set an |
| /// interrupt handler, or may do anything including ignore. But, if you know |
| /// your future supports this the most likely result is stopping or |
| /// preventing the asynchronous operation (if in time), and the promise |
| /// holder setting an exception on the future. (That may happen |
| /// asynchronously, of course.) |
| void raise(exception_wrapper interrupt); |
| |
| void cancel() { |
| raise(FutureCancellation()); |
| } |
| |
| /// Throw TimedOut if this Future does not complete within the given |
| /// duration from now. The optional Timeekeeper is as with futures::sleep(). |
| Future<T> within(Duration, Timekeeper* = nullptr); |
| |
| /// Throw the given exception if this Future does not complete within the |
| /// given duration from now. The optional Timeekeeper is as with |
| /// futures::sleep(). |
| template <class E> |
| Future<T> within(Duration, E exception, Timekeeper* = nullptr); |
| |
| /// Delay the completion of this Future for at least this duration from |
| /// now. The optional Timekeeper is as with futures::sleep(). |
| Future<T> delayed(Duration, Timekeeper* = nullptr); |
| |
| /// Block until this Future is complete. Returns a reference to this Future. |
| Future<T>& wait() &; |
| |
| /// Overload of wait() for rvalue Futures |
| Future<T>&& wait() &&; |
| |
| /// Block until this Future is complete or until the given Duration passes. |
| /// Returns a reference to this Future |
| Future<T>& wait(Duration) &; |
| |
| /// Overload of wait(Duration) for rvalue Futures |
| Future<T>&& wait(Duration) &&; |
| |
| /// Call e->drive() repeatedly until the future is fulfilled. Examples |
| /// of DrivableExecutor include EventBase and ManualExecutor. Returns a |
| /// reference to this Future so that you can chain calls if desired. |
| /// value (moved out), or throws the exception. |
| Future<T>& waitVia(DrivableExecutor* e) &; |
| |
| /// Overload of waitVia() for rvalue Futures |
| Future<T>&& waitVia(DrivableExecutor* e) &&; |
| |
| /// If the value in this Future is equal to the given Future, when they have |
| /// both completed, the value of the resulting Future<bool> will be true. It |
| /// will be false otherwise (including when one or both Futures have an |
| /// exception) |
| Future<bool> willEqual(Future<T>&); |
| |
| /// predicate behaves like std::function<bool(T const&)> |
| /// If the predicate does not obtain with the value, the result |
| /// is a folly::PredicateDoesNotObtain exception |
| template <class F> |
| Future<T> filter(F predicate); |
| |
| /// Like reduce, but works on a Future<std::vector<T / Try<T>>>, for example |
| /// the result of collect or collectAll |
| template <class I, class F> |
| Future<I> reduce(I&& initial, F&& func); |
| |
| /// Create a Future chain from a sequence of callbacks. i.e. |
| /// |
| /// f.then(a).then(b).then(c) |
| /// |
| /// where f is a Future<A> and the result of the chain is a Future<D> |
| /// becomes |
| /// |
| /// f.thenMulti(a, b, c); |
| template <class Callback, class... Callbacks> |
| auto thenMulti(Callback&& fn, Callbacks&&... fns) |
| -> decltype(this->then(std::forward<Callback>(fn)). |
| thenMulti(std::forward<Callbacks>(fns)...)); |
| |
| // Nothing to see here, just thenMulti's base case |
| template <class Callback> |
| auto thenMulti(Callback&& fn) |
| -> decltype(this->then(std::forward<Callback>(fn))); |
| |
| /// Create a Future chain from a sequence of callbacks. i.e. |
| /// |
| /// f.via(executor).then(a).then(b).then(c).via(oldExecutor) |
| /// |
| /// where f is a Future<A> and the result of the chain is a Future<D> |
| /// becomes |
| /// |
| /// f.thenMultiWithExecutor(executor, a, b, c); |
| template <class Callback, class... Callbacks, |
| typename = typename std::enable_if<!std::is_base_of<Cancellation, |
| typename std::remove_reference<Callback>::type>::value >::type> |
| auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns) |
| -> decltype(this->then(std::forward<Callback>(fn)). |
| thenMulti(std::forward<Callbacks>(fns)...)); |
| |
| // Nothing to see here, just thenMultiWithExecutor's base case |
| template <class Callback> |
| auto thenMultiWithExecutor(Executor* x, Callback&& fn) |
| -> decltype(this->then(std::forward<Callback>(fn))); |
| |
| /// Create a Future chain from a sequence of callbacks with Cancellation |
| /// |
| /// f.via(executor, cx).then(a).then(b).then(c).via(oldExecutor) |
| /// |
| /// where f is a Future<A> and the result of the chain is a Future<D> |
| /// becomes |
| /// |
| /// f.thenMultiWithExecutor(executor, cx, a, b, c); |
| template <class Callback, class... Callbacks> |
| auto thenMultiWithExecutor(Executor* x, const Cancellation &cx, Callback&& fn, Callbacks&&... fns) |
| -> decltype(this->then(std::forward<Callback>(fn)). |
| thenMulti(std::forward<Callbacks>(fns)...)); |
| // Nothing to see here, just thenMultiWithExecutor's base case |
| template <class Callback> |
| auto thenMultiWithExecutor(Executor* x, const Cancellation &cx, Callback&& fn) |
| -> decltype(this->then(std::forward<Callback>(fn))); |
| |
| // ExecutorWithCancellation |
| template <class Callback, class... Callbacks, |
| typename = typename std::enable_if<!std::is_base_of<Cancellation, |
| typename std::remove_reference<Callback>::type>::value >::type> |
| auto thenMultiWithExecutor(ExecutorWithCancellation* x, Callback&& fn, Callbacks&&... fns) |
| -> decltype(this->then(std::forward<Callback>(fn)). |
| thenMulti(std::forward<Callbacks>(fns)...)); |
| |
| // Nothing to see here, just thenMultiWithExecutor's base case |
| template <class Callback> |
| auto thenMultiWithExecutor(ExecutorWithCancellation* x, Callback&& fn) |
| -> decltype(this->then(std::forward<Callback>(fn))); |
| |
| /// Discard a result, but propagate an exception. |
| Future<Unit> unit() { |
| return then([]{ return Unit{}; }); |
| } |
| |
| protected: |
| typedef detail::Core<T>* corePtr; |
| |
| // shared core state object |
| corePtr core_; |
| |
| explicit |
| Future(corePtr obj) : core_(obj) {} |
| |
| void detach(); |
| |
| void throwIfInvalid() const; |
| |
| friend class Promise<T>; |
| template <class> friend class Future; |
| |
| template <class T2> |
| friend Future<T2> makeFuture(Try<T2>&&); |
| |
| /// Repeat the given future (i.e., the computation it contains) |
| /// n times. |
| /// |
| /// thunk behaves like std::function<Future<T2>(void)> |
| template <class F> |
| friend Future<Unit> times(const int n, F thunk); |
| |
| /// Carry out the computation contained in the given future if |
| /// the predicate holds. |
| /// |
| /// thunk behaves like std::function<Future<T2>(void)> |
| template <class F> |
| friend Future<Unit> when(bool p, F thunk); |
| |
| /// Carry out the computation contained in the given future if |
| /// while the predicate continues to hold. |
| /// |
| /// thunk behaves like std::function<Future<T2>(void)> |
| /// |
| /// predicate behaves like std::function<bool(void)> |
| template <class P, class F> |
| friend Future<Unit> whileDo(P predicate, F thunk); |
| |
| // Variant: returns a value |
| // e.g. f.then([](Try<T> t){ return t.value(); }); |
| template <typename F, typename R, bool isTry, typename... Args> |
| typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type |
| thenImplementation(F func, detail::argResult<isTry, F, Args...>); |
| |
| // Variant: returns a Future |
| // e.g. f.then([](Try<T> t){ return makeFuture<T>(t); }); |
| template <typename F, typename R, bool isTry, typename... Args> |
| typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type |
| thenImplementation(F func, detail::argResult<isTry, F, Args...>); |
| |
| Executor* getExecutor() { return core_->getExecutor(); } |
| void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) { |
| core_->setExecutor(x, priority); |
| } |
| |
| void setCancellation(Cancellation cx) { |
| core_->setCancellation(std::move(cx)); |
| } |
| |
| }; |
| |
| } // folly |
| |
| #include <folly/futures/Future-inl.h> |