+ SemiFuture(SemiFuture<T>&&) noexcept;
+ // safe move-constructabilty from Future
+ /* implicit */ SemiFuture(Future<T>&&) noexcept;
+
+ using Base::cancel;
+ using Base::hasException;
+ using Base::hasValue;
+ using Base::isActive;
+ using Base::isReady;
+ using Base::poll;
+ using Base::raise;
+ using Base::setCallback_;
+ using Base::value;
+ using Base::result;
+
+ SemiFuture& operator=(SemiFuture const&) = delete;
+ SemiFuture& operator=(SemiFuture&&) noexcept;
+ SemiFuture& operator=(Future<T>&&) noexcept;
+
+ /// 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) &&;
+
+ /// Block until the future is fulfilled, or until timed out. Returns the
+ /// Try of the value (moved out).
+ Try<T> getTry() &&;
+
+ /// Block until the future is fulfilled, or until timed out. Returns the
+ /// Try of the value (moved out) or may throw a TimedOut exception.
+ Try<T> getTry(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) &&;
+
+ /// Call e->drive() repeatedly until the future is fulfilled. Examples
+ /// of DrivableExecutor include EventBase and ManualExecutor. Returns the
+ /// Try of the value (moved out).
+ Try<T> getTryVia(DrivableExecutor* e) &&;
+
+ /// Block until this Future is complete. Returns a reference to this Future.
+ SemiFuture<T>& wait() &;
+
+ /// Overload of wait() for rvalue Futures
+ SemiFuture<T>&& wait() &&;
+
+ /// Block until this Future is complete or until the given Duration passes.
+ /// Returns a reference to this Future
+ SemiFuture<T>& wait(Duration) &;
+
+ /// Overload of wait(Duration) for rvalue Futures
+ SemiFuture<T>&& wait(Duration) &&;
+
+ /// Call e->drive() repeatedly until the future is fulfilled. Examples
+ /// of DrivableExecutor include EventBase and ManualExecutor. Returns a
+ /// reference to this SemiFuture so that you can chain calls if desired.
+ /// value (moved out), or throws the exception.
+ SemiFuture<T>& waitVia(DrivableExecutor* e) &;
+
+ /// Overload of waitVia() for rvalue Futures
+ SemiFuture<T>&& waitVia(DrivableExecutor* e) &&;
+
+ /// 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) &&;
+
+ /**
+ * Defer work to run on the consumer of the future.
+ * This work will be run eithe ron an executor that the caller sets on the
+ * SemiFuture, or inline with the call to .get().
+ * NB: This is a custom method because boost-blocking executors is a
+ * special-case for work deferral in folly. With more general boost-blocking
+ * support all executors would boost block and we would simply use some form
+ * of driveable executor here.
+ */
+ template <typename F>
+ SemiFuture<typename futures::detail::callableResult<T, F>::Return::value_type>
+ defer(F&& func) &&;
+
+ // Public as for setCallback_
+ // Ensure that a boostable executor performs work to chain deferred work
+ // cleanly
+ void boost_();
+
+ private:
+ friend class Promise<T>;
+ template <class>
+ friend class futures::detail::FutureBase;
+ template <class>
+ friend class SemiFuture;
+
+ using typename Base::corePtr;
+ using Base::setExecutor;
+ using Base::throwIfInvalid;
+
+ template <class T2>
+ friend SemiFuture<T2> makeSemiFuture(Try<T2>&&);
+
+ explicit SemiFuture(corePtr obj) : Base(obj) {}
+
+ explicit SemiFuture(futures::detail::EmptyConstruct) noexcept
+ : Base(futures::detail::EmptyConstruct{}) {}
+};
+
+template <class T>
+class Future : private futures::detail::FutureBase<T> {
+ private:
+ using Base = futures::detail::FutureBase<T>;
+
+ public:
+ // Export public interface of FutureBase
+ // FutureBase is inherited privately to avoid subclasses being cast to
+ // a FutureBase pointer
+ using typename Base::value_type;
+
+ /// Construct a Future from a value (perfect forwarding)
+ template <
+ class T2 = T,
+ typename = typename std::enable_if<
+ !isFuture<typename std::decay<T2>::type>::value &&
+ !isSemiFuture<typename std::decay<T2>::type>::value>::type>
+ /* implicit */ Future(T2&& val) : Base(std::forward<T2>(val)) {}
+
+ template <class T2 = T>
+ /* implicit */ Future(
+ typename std::enable_if<std::is_same<Unit, T2>::value>::type* p = nullptr)
+ : Base(p) {}
+
+ template <
+ class... Args,
+ typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
+ type = 0>
+ explicit Future(in_place_t, Args&&... args)
+ : Base(in_place, std::forward<Args>(args)...) {}
+
+ Future(Future<T> const&) = delete;
+ // movable
+ Future(Future<T>&&) noexcept;