Make consistent set of get and getTry methods on SemiFuture.
[folly.git] / folly / futures / Future.h
index 948e263a22b3bc6e4dca80afc5289bbed37d9077..5b2dc82f7b44b6c8f9a4a910f1f17fdb0c6c1204 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
 
 #include <algorithm>
 #include <type_traits>
 #include <vector>
 
-#include <folly/MoveWrapper.h>
-#include <folly/futures/Deprecated.h>
-#include <folly/futures/DrivableExecutor.h>
-#include <folly/futures/Promise.h>
-#include <folly/futures/Try.h>
+#include <folly/Optional.h>
+#include <folly/Portability.h>
+#include <folly/ScopeGuard.h>
+#include <folly/Try.h>
+#include <folly/Utility.h>
+#include <folly/executors/DrivableExecutor.h>
 #include <folly/futures/FutureException.h>
+#include <folly/futures/Promise.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 {
 
-template <class> struct Promise;
+template <class T>
+class Future;
+
+template <class T>
+class SemiFuture;
 
+namespace futures {
 namespace detail {
+template <class T>
+class FutureBase {
+ public:
+  typedef T value_type;
 
-template <class> struct Core;
-template <class...> struct VariadicContext;
+  /// 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 */ FutureBase(T2&& val);
 
-template <class T>
-struct AliasIfVoid {
-  typedef typename std::conditional<
-    std::is_same<T, void>::value,
-    int,
-    T>::type type;
-};
+  template <class T2 = T>
+  /* implicit */ FutureBase(
+      typename std::enable_if<std::is_same<Unit, T2>::value>::type*);
 
+  template <
+      class... Args,
+      typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
+          type = 0>
+  explicit FutureBase(in_place_t, Args&&... args);
 
-template <typename T>
-struct IsFuture : std::integral_constant<bool, false> {
-    typedef T Inner;
-};
+  FutureBase(FutureBase<T> const&) = delete;
+  FutureBase(SemiFuture<T>&&) noexcept;
+  FutureBase(Future<T>&&) noexcept;
 
-template <template <typename T> class Future, typename T>
-struct IsFuture<Future<T>> : std::integral_constant<bool, true> {
-    typedef T Inner;
-};
+  // not copyable
+  FutureBase(Future<T> const&) = delete;
+  FutureBase(SemiFuture<T> const&) = delete;
 
-template <typename...>
-struct ArgType;
+  ~FutureBase();
 
-template <typename Arg, typename... Args>
-struct ArgType<Arg, Args...> {
-  typedef Arg FirstArg;
-};
+  /// Returns a reference to the result, with a reference category and const-
+  /// qualification equivalent to the reference category and const-qualification
+  /// of the receiver.
+  ///
+  /// If moved-from, throws NoState.
+  ///
+  /// If !isReady(), throws FutureNotReady.
+  ///
+  /// If an exception has been captured, throws that exception.
+  T& value() &;
+  T const& value() const&;
+  T&& value() &&;
+  T const&& value() const&&;
+
+  /// Returns a reference to the try of the result. Throws as for value if
+  /// future is not valid.
+  Try<T>& result() &;
+  Try<T> const& result() const&;
+  Try<T>&& result() &&;
+  Try<T> const&& result() const&&;
 
-template <>
-struct ArgType<> {
-  typedef void FirstArg;
-};
+  /** True when the result (or exception) is ready. */
+  bool isReady() const;
 
-template <typename L>
-struct Extract : Extract<decltype(&L::operator())> { };
+  /// sugar for getTry().hasValue()
+  bool hasValue();
 
-template <typename Class, typename R, typename... Args>
-struct Extract<R(Class::*)(Args...) const> {
-  typedef IsFuture<R> ReturnsFuture;
-  typedef Future<typename ReturnsFuture::Inner> Return;
-  typedef typename ReturnsFuture::Inner RawReturn;
-  typedef typename ArgType<Args...>::FirstArg FirstArg;
-};
+  /// sugar for getTry().hasException()
+  bool hasException();
 
-template <typename Class, typename R, typename... Args>
-struct Extract<R(Class::*)(Args...)> {
-  typedef IsFuture<R> ReturnsFuture;
-  typedef Future<typename ReturnsFuture::Inner> Return;
-  typedef typename ReturnsFuture::Inner RawReturn;
-  typedef typename ArgType<Args...>::FirstArg FirstArg;
-};
+  /// 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();
 
-} // detail
+  /// 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);
 
-struct Timekeeper;
+  bool isActive() {
+    return core_->isActive();
+  }
 
-template <typename T> struct isFuture;
+  template <class E>
+  void raise(E&& exception) {
+    raise(make_exception_wrapper<typename std::remove_reference<E>::type>(
+        std::forward<E>(exception)));
+  }
 
-/// This namespace is for utility functions that would usually be static
-/// members of Future, except they don't make sense there because they don't
-/// depend on the template type (rather, on the type of their arguments in
-/// some cases). This is the least-bad naming scheme we could think of. Some
-/// of the functions herein have really-likely-to-collide names, like "map"
-/// and "sleep".
-namespace futures {
-  /// Returns a Future that will complete after the specified duration. The
-  /// Duration typedef of a `std::chrono` duration type indicates the
-  /// resolution you can expect to be meaningful (milliseconds at the time of
-  /// writing). Normally you wouldn't need to specify a Timekeeper, we will
-  /// use the global futures timekeeper (we run a thread whose job it is to
-  /// keep time for futures timeouts) but we provide the option for power
-  /// users.
-  ///
-  /// The Timekeeper thread will be lazily created the first time it is
-  /// needed. If your program never uses any timeouts or other time-based
-  /// Futures you will pay no Timekeeper thread overhead.
-  Future<void> sleep(Duration, Timekeeper* = nullptr);
-}
+  /// 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());
+  }
+
+ protected:
+  friend class Promise<T>;
+  template <class>
+  friend class SemiFuture;
+  template <class>
+  friend class Future;
+
+  using corePtr = futures::detail::Core<T>*;
+
+  // shared core state object
+  corePtr core_;
+
+  explicit FutureBase(corePtr obj) : core_(obj) {}
+
+  explicit FutureBase(futures::detail::EmptyConstruct) noexcept;
+
+  void detach();
+
+  void throwIfInvalid() const;
+
+  template <class FutureType>
+  void assign(FutureType&) noexcept;
+
+  Executor* getExecutor() {
+    return core_->getExecutor();
+  }
+
+  void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {
+    core_->setExecutor(x, priority);
+  }
+
+  // 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, futures::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, futures::detail::argResult<isTry, F, Args...>);
+};
+} // namespace detail
+} // namespace futures
 
 template <class T>
-class Future {
+class SemiFuture : private futures::detail::FutureBase<T> {
+ private:
+  using Base = futures::detail::FutureBase<T>;
+  using DeferredExecutor = futures::detail::DeferredExecutor;
+
  public:
-  typedef T value_type;
+  static SemiFuture<T> makeEmpty(); // equivalent to moved-from
+
+  // 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 */ SemiFuture(T2&& val) : Base(std::forward<T2>(val)) {}
+
+  template <class T2 = T>
+  /* implicit */ SemiFuture(
+      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 SemiFuture(in_place_t, Args&&... args)
+      : Base(in_place, std::forward<Args>(args)...) {}
+
+  SemiFuture(SemiFuture<T> const&) = delete;
+  // movable
+  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;
 
-  // not copyable
-  Future(Future const&) = delete;
-  Future& operator=(Future const&) = delete;
+  /// 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() &&;
 
-  // movable
-  Future(Future&&) noexcept;
-  Future& operator=(Future&&);
+  /// 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) &&;
 
-  ~Future();
+  /// Block until the future is fulfilled, or until timed out. Returns the
+  /// Try of the value (moved out).
+  Try<T> getTry() &&;
 
-  /** Return the reference to result. Should not be called if !isReady().
-    Will rethrow the exception if an exception has been
-    captured.
+  /// 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) &&;
 
-    This function is not thread safe - the returned Future can only
-    be executed from the thread that the executor runs it in.
-    See below for a thread safe version
-    */
-  typename std::add_lvalue_reference<T>::type
-  value();
-  typename std::add_lvalue_reference<const T>::type
-  value() const;
+  /// 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).
@@ -166,38 +319,188 @@ class Future {
   // 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/
-  template <typename Executor>
-  Future<T> via(Executor* executor) &&;
+  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_();
 
-  /// 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.
-  template <typename Executor>
-  Future<T> via(Executor* executor) &;
+ private:
+  friend class Promise<T>;
+  template <class>
+  friend class futures::detail::FutureBase;
+  template <class>
+  friend class SemiFuture;
 
-  /** True when the result (or exception) is ready. */
-  bool isReady() const;
+  using typename Base::corePtr;
+  using Base::setExecutor;
+  using Base::throwIfInvalid;
 
-  /** A reference to the Try of the value */
-  Try<T>& getTry();
+  template <class T2>
+  friend SemiFuture<T2> makeSemiFuture(Try<T2>&&);
 
-  /// 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();
+  explicit SemiFuture(corePtr obj) : Base(obj) {}
 
-  /// 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);
+  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;
+
+  // converting move
+  template <
+      class T2,
+      typename std::enable_if<
+          !std::is_same<T, typename std::decay<T2>::type>::value &&
+              std::is_constructible<T, T2&&>::value &&
+              std::is_convertible<T2&&, T>::value,
+          int>::type = 0>
+  /* implicit */ Future(Future<T2>&&);
+  template <
+      class T2,
+      typename std::enable_if<
+          !std::is_same<T, typename std::decay<T2>::type>::value &&
+              std::is_constructible<T, T2&&>::value &&
+              !std::is_convertible<T2&&, T>::value,
+          int>::type = 0>
+  explicit Future(Future<T2>&&);
+  template <
+      class T2,
+      typename std::enable_if<
+          !std::is_same<T, typename std::decay<T2>::type>::value &&
+              std::is_constructible<T, T2&&>::value,
+          int>::type = 0>
+  Future& operator=(Future<T2>&&);
+
+  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;
+
+  static Future<T> makeEmpty(); // equivalent to moved-from
+
+  // not copyable
+  Future& operator=(Future const&) = delete;
+
+  // movable
+  Future& operator=(Future&&) noexcept;
 
   /// 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 a
+  /// reference to the Try of the value.
+  Try<T>& getTryVia(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();
+
+  /// 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) &;
+
   /** When this Future has completed, execute func which is a function that
-    takes a Try<T>&&. A Future for the return type of func is
-    returned. e.g.
+    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"); });
 
@@ -205,188 +508,58 @@ class Future {
     value(), which may rethrow if this has captured an exception. If func
     throws, the exception will be captured in the Future that is returned.
     */
-  /* TODO n3428 and other async frameworks have something like then(scheduler,
-     Future), we might want to support a similar API which could be
-     implemented a little more efficiently than
-     f.via(executor).then(callback) */
-  template <class F>
-  typename std::enable_if<
-    !isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
-    Future<typename std::result_of<F(Try<T>&&)>::type> >::type
-  then(F&& func);
+  template <typename F, typename R = futures::detail::callableResult<T, F>>
+  typename R::Return then(F&& func) {
+    return this->template thenImplementation<F, R>(
+        std::forward<F>(func), typename R::Arg());
+  }
 
-  /// Variant where func takes a T directly, bypassing a try. Any exceptions
-  /// will be implicitly passed on to the resultant Future.
+  /// Variant where func is an member function
   ///
-  ///   Future<int> f = makeFuture<int>(42).then([](int i) { return i+1; });
-  template <class F>
-  typename std::enable_if<
-    !std::is_same<T, void>::value &&
-    !isFuture<typename std::result_of<
-      F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
-    Future<typename std::result_of<
-      F(typename detail::AliasIfVoid<T>::type&&)>::type> >::type
-  then(F&& func);
-
-  /// Like the above variant, but for void futures. That is, func takes no
-  /// argument.
+  ///   struct Worker { R doWork(Try<T>); }
   ///
-  ///   Future<int> f = makeFuture().then([] { return 42; });
-  template <class F>
-  typename std::enable_if<
-    std::is_same<T, void>::value &&
-    !isFuture<typename std::result_of<F()>::type>::value,
-    Future<typename std::result_of<F()>::type> >::type
-  then(F&& func);
-
-  /// Variant where func returns a Future<T> instead of a T. e.g.
+  ///   Worker *w;
+  ///   Future<R> f2 = f1.then(&Worker::doWork, w);
   ///
-  ///   Future<string> f2 = f1.then(
-  ///     [](Try<T>&&) { return makeFuture<string>("foo"); });
-  template <class F>
-  typename std::enable_if<
-    isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
-    Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
-  then(F&& func);
-
-  /// Variant where func returns a Future<T2> and takes a T directly, bypassing
-  /// a Try. Any exceptions will be implicitly passed on to the resultant
-  /// Future. For example,
+  /// This is just sugar for
   ///
-  ///   Future<int> f = makeFuture<int>(42).then(
-  ///     [](int i) { return makeFuture<int>(i+1); });
-  template <class F>
-  typename std::enable_if<
-    !std::is_same<T, void>::value &&
-    isFuture<typename std::result_of<
-      F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
-    Future<typename std::result_of<
-      F(typename detail::AliasIfVoid<T>::type&&)>::type::value_type> >::type
-  then(F&& func);
-
-  /// Like the above variant, but for void futures. That is, func takes no
-  /// argument and returns a future.
-  ///
-  ///   Future<int> f = makeFuture().then(
-  ///     [] { return makeFuture<int>(42); });
-  template <class F>
-  typename std::enable_if<
-    std::is_same<T, void>::value &&
-    isFuture<typename std::result_of<F()>::type>::value,
-    Future<typename std::result_of<F()>::type::value_type> >::type
-  then(F&& func);
+  ///   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);
 
-  /// Variant where func is an ordinary function (static method, method)
+  /// Execute the callback via the given Executor. The executor doesn't stick.
   ///
-  ///   R doWork(Try<T>&&);
+  /// Contrast
   ///
-  ///   Future<R> f2 = f1.then(doWork);
+  ///   f.via(x).then(b).then(c)
   ///
-  /// or
+  /// with
   ///
-  ///   struct Worker {
-  ///     static R doWork(Try<T>&&); }
+  ///   f.then(x, b).then(c)
   ///
-  ///   Future<R> f2 = f1.then(&Worker::doWork);
-  template <class = T, class R = std::nullptr_t>
-  typename std::enable_if<!isFuture<R>::value, Future<R>>::type
-  inline then(R(*func)(Try<T>&&)) {
-    return then([func](Try<T>&& t) {
-      return (*func)(std::move(t));
-    });
-  }
-
-  /// Variant where func returns a Future<R> instead of a R. e.g.
-  ///
-  ///   struct Worker {
-  ///     Future<R> doWork(Try<T>&&); }
-  ///
-  ///   Future<R> f2 = f1.then(&Worker::doWork);
-  template <class = T, class R = std::nullptr_t>
-  typename std::enable_if<isFuture<R>::value, R>::type
-  inline then(R(*func)(Try<T>&&)) {
-    return then([func](Try<T>&& t) {
-      return (*func)(std::move(t));
-    });
-  }
-
-  /// Variant where func is an member function
-  ///
-  ///   struct Worker {
-  ///     R doWork(Try<T>&&); }
-  ///
-  ///   Worker *w;
-  ///   Future<R> f2 = f1.then(w, &Worker::doWork);
-  template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
-  typename std::enable_if<!isFuture<R>::value, Future<R>>::type
-  inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
-    return then([instance, func](Try<T>&& t) {
-      return (instance->*func)(std::move(t));
-    });
+  /// 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) {
+    auto oldX = this->getExecutor();
+    this->setExecutor(x);
+    return this->then(std::forward<Arg>(arg), std::forward<Args>(args)...)
+        .via(oldX);
   }
 
-  // Same as above, but func takes void instead of Try<void>&&
-  template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
-  typename std::enable_if<
-      std::is_same<T, void>::value && !isFuture<R>::value, Future<R>>::type
-  inline then(Caller *instance, R(Caller::*func)()) {
-    return then([instance, func]() {
-      return (instance->*func)();
-    });
-  }
-
-  // Same as above, but func takes T&& instead of Try<T>&&
-  template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
-  typename std::enable_if<
-      !std::is_same<T, void>::value && !isFuture<R>::value, Future<R>>::type
-  inline then(
-      Caller *instance,
-      R(Caller::*func)(typename detail::AliasIfVoid<T>::type&&)) {
-    return then([instance, func](T&& t) {
-      return (instance->*func)(std::move(t));
-    });
-  }
-
-  /// Variant where func returns a Future<R> instead of a R. e.g.
-  ///
-  ///   struct Worker {
-  ///     Future<R> doWork(Try<T>&&); }
-  ///
-  ///   Worker *w;
-  ///   Future<R> f2 = f1.then(w, &Worker::doWork);
-  template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
-  typename std::enable_if<isFuture<R>::value, R>::type
-  inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
-    return then([instance, func](Try<T>&& t) {
-      return (instance->*func)(std::move(t));
-    });
-  }
-
-  // Same as above, but func takes void instead of Try<void>&&
-  template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
-  typename std::enable_if<
-      std::is_same<T, void>::value && isFuture<R>::value, R>::type
-  inline then(Caller *instance, R(Caller::*func)()) {
-    return then([instance, func]() {
-      return (instance->*func)();
-    });
-  }
-
-  // Same as above, but func takes T&& instead of Try<T>&&
-  template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
-  typename std::enable_if<
-      !std::is_same<T, void>::value && isFuture<R>::value, R>::type
-  inline then(
-      Caller *instance,
-      R(Caller::*func)(typename detail::AliasIfVoid<T>::type&&)) {
-    return then([instance, func](T&& t) {
-      return (instance->*func)(std::move(t));
-    });
-  }
+  /// Convenience method for ignoring the value and creating a Future<Unit>.
+  /// Exceptions still propagate.
+  /// This function is identical to .unit().
+  Future<Unit> then();
 
-  /// Convenience method for ignoring the value and creating a Future<void>.
+  /// Convenience method for ignoring the value and creating a Future<Unit>.
   /// Exceptions still propagate.
-  Future<void> then();
+  /// This function is identical to parameterless .then().
+  Future<Unit> unit() {
+    return 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
@@ -404,71 +577,82 @@ class Future {
   ///   });
   template <class F>
   typename std::enable_if<
-    !detail::Extract<F>::ReturnsFuture::value,
-    Future<T>>::type
+      !futures::detail::callableWith<F, exception_wrapper>::value &&
+          !futures::detail::callableWith<F, exception_wrapper&>::value &&
+          !futures::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::Extract<F>::ReturnsFuture::value,
-    Future<T>>::type
+      !futures::detail::callableWith<F, exception_wrapper>::value &&
+          !futures::detail::callableWith<F, exception_wrapper&>::value &&
+          futures::detail::Extract<F>::ReturnsFuture::value,
+      Future<T>>::type
   onError(F&& func);
 
-  /// This is not the method you're looking for.
+  /// Overload of onError that takes exception_wrapper and returns Future<T>
+  template <class F>
+  typename std::enable_if<
+      futures::detail::callableWith<F, exception_wrapper>::value &&
+          futures::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<
+      futures::detail::callableWith<F, exception_wrapper>::value &&
+          !futures::detail::Extract<F>::ReturnsFuture::value,
+      Future<T>>::type
+  onError(F&& func);
+
+  /// 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:
   ///
-  /// 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.
+  ///   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>
-  void setCallback_(F&& func);
+  Future<T> onTimeout(Duration, F&& func, Timekeeper* = nullptr);
 
   /// 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.
-  Future<T>& activate() & {
-    core_->activate();
+  FOLLY_DEPRECATED("do not use") Future<T>& activate() & {
+    this->core_->activate();
     return *this;
   }
-  Future<T>& deactivate() & {
-    core_->deactivate();
+  FOLLY_DEPRECATED("do not use") Future<T>& deactivate() & {
+    this->core_->deactivate();
     return *this;
   }
-  Future<T> activate() && {
-    core_->activate();
+  FOLLY_DEPRECATED("do not use") Future<T> activate() && {
+    this->core_->activate();
     return std::move(*this);
   }
-  Future<T> deactivate() && {
-    core_->deactivate();
+  FOLLY_DEPRECATED("do not use") Future<T> deactivate() && {
+    this->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);
@@ -483,14 +667,30 @@ class Future {
   /// now. The optional Timekeeper is as with futures::sleep().
   Future<T> delayed(Duration, Timekeeper* = nullptr);
 
-  /// Block until this Future is complete. Returns a new Future containing the
-  /// result.
-  Future<T> wait();
+  /// 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);
+
+  /** A reference to the Try of the value */
+  Try<T>& getTry();
+
+  /// 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 new Future which either contains the result or is incomplete,
-  /// depending on whether the Duration passed.
-  Future<T> wait(Duration);
+  /// 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
@@ -499,156 +699,122 @@ class Future {
   Future<T>& waitVia(DrivableExecutor* e) &;
 
   /// Overload of waitVia() for rvalue Futures
-  Future<T> waitVia(DrivableExecutor* e) &&;
+  Future<T>&& waitVia(DrivableExecutor* e) &&;
 
- private:
-  typedef detail::Core<T>* corePtr;
-
-  // shared core state object
-  corePtr core_;
+  /// 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>&);
 
-  explicit
-  Future(corePtr obj) : core_(obj) {}
+  /// 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);
 
-  void detach();
+  /// 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);
 
-  void throwIfInvalid() const;
+  /// 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) {
+    // thenMulti with two callbacks is just then(a).thenMulti(b, ...)
+    return then(std::forward<Callback>(fn))
+        .thenMulti(std::forward<Callbacks>(fns)...);
+  }
 
-  friend class Promise<T>;
-};
+  template <class Callback>
+  auto thenMulti(Callback&& fn) {
+    // thenMulti with one callback is just a then
+    return then(std::forward<Callback>(fn));
+  }
 
-/**
-  Make a completed Future by moving in a value. e.g.
+  /// 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>
+  auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns) {
+    // thenMultiExecutor with two callbacks is
+    // via(x).then(a).thenMulti(b, ...).via(oldX)
+    auto oldX = this->getExecutor();
+    this->setExecutor(x);
+    return then(std::forward<Callback>(fn))
+        .thenMulti(std::forward<Callbacks>(fns)...)
+        .via(oldX);
+  }
 
-    string foo = "foo";
-    auto f = makeFuture(std::move(foo));
+  template <class Callback>
+  auto thenMultiWithExecutor(Executor* x, Callback&& fn) {
+    // thenMulti with one callback is just a then with an executor
+    return then(x, std::forward<Callback>(fn));
+  }
 
-  or
+  // Convert this Future to a SemiFuture to safely export from a library
+  // without exposing a continuation interface
+  SemiFuture<T> semi() {
+    return SemiFuture<T>{std::move(*this)};
+  }
 
-    auto f = makeFuture<string>("foo");
-*/
-template <class T>
-Future<typename std::decay<T>::type> makeFuture(T&& t);
+ protected:
+  friend class Promise<T>;
+  template <class>
+  friend class futures::detail::FutureBase;
+  template <class>
+  friend class Future;
+  template <class>
+  friend class SemiFuture;
 
-/** Make a completed void Future. */
-Future<void> makeFuture();
+  using Base::setExecutor;
+  using Base::throwIfInvalid;
+  using typename Base::corePtr;
 
-/** Make a completed Future by executing a function. If the function throws
-  we capture the exception, otherwise we capture the result. */
-template <class F>
-auto makeFutureTry(
-  F&& func,
-  typename std::enable_if<
-    !std::is_reference<F>::value, bool>::type sdf = false)
-  -> Future<decltype(func())>;
-
-template <class F>
-auto makeFutureTry(
-  F const& func)
-  -> Future<decltype(func())>;
-
-/// Make a failed Future from an exception_ptr.
-/// Because the Future's type cannot be inferred you have to specify it, e.g.
-///
-///   auto f = makeFuture<string>(std::current_exception());
-template <class T>
-Future<T> makeFuture(std::exception_ptr const& e) DEPRECATED;
+  explicit Future(corePtr obj) : Base(obj) {}
 
-/// Make a failed Future from an exception_wrapper.
-template <class T>
-Future<T> makeFuture(exception_wrapper ew);
+  explicit Future(futures::detail::EmptyConstruct) noexcept
+      : Base(futures::detail::EmptyConstruct{}) {}
 
-/** Make a Future from an exception type E that can be passed to
-  std::make_exception_ptr(). */
-template <class T, class E>
-typename std::enable_if<std::is_base_of<std::exception, E>::value,
-                        Future<T>>::type
-makeFuture(E const& e);
+  template <class T2>
+  friend Future<T2> makeFuture(Try<T2>&&);
 
-/** Make a Future out of a Try */
-template <class T>
-Future<T> makeFuture(Try<T>&& t);
+  /// 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(int n, F&& thunk);
 
-/*
- * Return a new Future that will call back on the given Executor.
- * This is just syntactic sugar for makeFuture().via(executor)
- *
- * @param executor the Executor to call back on
- *
- * @returns a void Future that will call back on the given executor
- */
-template <typename Executor>
-Future<void> via(Executor* executor);
-
-/** When all the input Futures complete, the returned Future will complete.
-  Errors do not cause early termination; this Future will always succeed
-  after all its Futures have finished (whether successfully or with an
-  error).
-
-  The Futures are moved in, so your copies are invalid. If you need to
-  chain further from these Futures, use the variant with an output iterator.
-
-  XXX is this still true?
-  This function is thread-safe for Futures running on different threads.
-
-  The return type for Future<T> input is a Future<std::vector<Try<T>>>
-  */
-template <class InputIterator>
-Future<std::vector<Try<
-  typename std::iterator_traits<InputIterator>::value_type::value_type>>>
-whenAll(InputIterator first, InputIterator last);
-
-/// This version takes a varying number of Futures instead of an iterator.
-/// The return type for (Future<T1>, Future<T2>, ...) input
-/// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
-/// The Futures are moved in, so your copies are invalid.
-template <typename... Fs>
-typename detail::VariadicContext<
-  typename std::decay<Fs>::type::value_type...>::type
-whenAll(Fs&&... fs);
-
-/** The result is a pair of the index of the first Future to complete and
-  the Try. If multiple Futures complete at the same time (or are already
-  complete when passed in), the "winner" is chosen non-deterministically.
-
-  This function is thread-safe for Futures running on different threads.
-  */
-template <class InputIterator>
-Future<std::pair<
-  size_t,
-  Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
-whenAny(InputIterator first, InputIterator last);
-
-/** when n Futures have completed, the Future completes with a vector of
-  the index and Try of those n Futures (the indices refer to the original
-  order, but the result vector will be in an arbitrary order)
-
-  Not thread safe.
-  */
-template <class InputIterator>
-Future<std::vector<std::pair<
-  size_t,
-  Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
-whenN(InputIterator first, InputIterator last, size_t n);
-
-/** Wait for the given future to complete on a semaphore. Returns a completed
- * future containing the result.
- *
- * NB if the promise for the future would be fulfilled in the same thread that
- * you call this, it will deadlock.
- */
-template <class T>
-Future<T> waitWithSemaphore(Future<T>&& f);
+  /// 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);
 
-/** Wait for up to `timeout` for the given future to complete. Returns a future
- * which may or may not be completed depending whether the given future
- * completed in time
- *
- * Note: each call to this starts a (short-lived) thread and allocates memory.
- */
-template <typename T, class Dur>
-Future<T> waitWithSemaphore(Future<T>&& f, Dur timeout);
+  /// 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);
+};
 
-} // folly
+} // namespace folly
 
 #include <folly/futures/Future-inl.h>