Protect unprotected
[folly.git] / folly / futures / Future.h
index 494bf6e1217fe4255e5d0529573ef6ca0e5467eb..2b81407f55c50a6dc347907fd9b1d11660060a65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * 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.
 
 #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/futures/WangleException.h>
+#include <folly/futures/FutureException.h>
 #include <folly/futures/detail/Types.h>
 
 namespace folly {
 
 template <class> struct Promise;
 
-namespace detail {
-
-template <class> struct Core;
-template <class...> struct VariadicContext;
+template <typename T>
+struct isFuture : std::false_type {
+  typedef T Inner;
+};
 
-template <class T>
-struct AliasIfVoid {
-  typedef typename std::conditional<
-    std::is_same<T, void>::value,
-    int,
-    T>::type type;
+template <typename T>
+struct isFuture<Future<T>> : std::true_type {
+  typedef T Inner;
 };
 
+template <typename T>
+struct isTry : std::false_type {};
 
 template <typename T>
-struct IsFuture : std::integral_constant<bool, false> {
-    typedef T Inner;
-};
+struct isTry<Try<T>> : std::true_type {};
 
-template <template <typename T> class Future, typename T>
-struct IsFuture<Future<T>> : std::integral_constant<bool, true> {
-    typedef T Inner;
-};
+namespace detail {
+
+template <class> struct Core;
+template <class...> struct VariadicContext;
+
+template<typename F, typename... Args>
+using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
 
 template <typename...>
 struct ArgType;
@@ -71,12 +72,64 @@ struct ArgType<> {
   typedef void FirstArg;
 };
 
+template <bool isTry, typename F, typename... Args>
+struct argResult {
+  typedef resultOf<F, Args...> Result;
+};
+
+template<typename F, typename... Args>
+struct callableWith {
+    template<typename T,
+             typename = detail::resultOf<T, Args...>>
+    static constexpr std::true_type
+    check(std::nullptr_t) { return std::true_type{}; };
+
+    template<typename>
+    static constexpr std::false_type
+    check(...) { return std::false_type{}; };
+
+    typedef decltype(check<F>(nullptr)) type;
+    static constexpr bool value = type::value;
+};
+
+template<typename T, typename F>
+struct callableResult {
+  typedef typename std::conditional<
+    callableWith<F>::value,
+    detail::argResult<false, F>,
+    typename std::conditional<
+      callableWith<F, Try<T>&&>::value,
+      detail::argResult<true, F, Try<T>&&>,
+      typename std::conditional<
+        callableWith<F, Try<T>&>::value,
+        detail::argResult<true, F, Try<T>&>,
+        typename std::conditional<
+          callableWith<F, T&&>::value,
+          detail::argResult<false, F, T&&>,
+          detail::argResult<false, F, T&>>::type>::type>::type>::type Arg;
+  typedef isFuture<typename Arg::Result> ReturnsFuture;
+  typedef Future<typename ReturnsFuture::Inner> Return;
+};
+
+template<typename F>
+struct callableResult<void, F> {
+  typedef typename std::conditional<
+    callableWith<F>::value,
+    detail::argResult<false, F>,
+    typename std::conditional<
+      callableWith<F, Try<void>&&>::value,
+      detail::argResult<true, F, Try<void>&&>,
+      detail::argResult<true, F, Try<void>&>>::type>::type Arg;
+  typedef isFuture<typename Arg::Result> ReturnsFuture;
+  typedef Future<typename ReturnsFuture::Inner> Return;
+};
+
 template <typename L>
 struct Extract : Extract<decltype(&L::operator())> { };
 
 template <typename Class, typename R, typename... Args>
 struct Extract<R(Class::*)(Args...) const> {
-  typedef IsFuture<R> ReturnsFuture;
+  typedef isFuture<R> ReturnsFuture;
   typedef Future<typename ReturnsFuture::Inner> Return;
   typedef typename ReturnsFuture::Inner RawReturn;
   typedef typename ArgType<Args...>::FirstArg FirstArg;
@@ -84,19 +137,16 @@ struct Extract<R(Class::*)(Args...) const> {
 
 template <typename Class, typename R, typename... Args>
 struct Extract<R(Class::*)(Args...)> {
-  typedef IsFuture<R> ReturnsFuture;
+  typedef isFuture<R> ReturnsFuture;
   typedef Future<typename ReturnsFuture::Inner> Return;
   typedef typename ReturnsFuture::Inner RawReturn;
   typedef typename ArgType<Args...>::FirstArg FirstArg;
 };
 
-
 } // detail
 
 struct Timekeeper;
 
-template <typename T> struct isFuture;
-
 /// 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
@@ -108,14 +158,27 @@ namespace futures {
   /// 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 wangle timekeeper (we run a thread whose job it is to
-  /// keep time for wangle timeouts) but we provide the option for power
+  /// 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);
+
+  /// 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<Z>
+  /// becomes
+  ///
+  ///   f.then(chain<A,Z>(a, b, c));
+  // If anyone figures how to get chain to deduce A and Z, I'll buy you a drink.
+  template <class A, class Z, class... Callbacks>
+  std::function<Future<Z>(Try<A>)>
+  chain(Callbacks... fns);
 }
 
 template <class T>
@@ -131,15 +194,24 @@ class Future {
   Future(Future&&) noexcept;
   Future& operator=(Future&&);
 
+  // makeFuture
+  template <class F = T>
+  /* implicit */
+  Future(const typename std::enable_if<!std::is_void<F>::value, F>::type& val);
+
+  template <class F = T>
+  /* implicit */
+  Future(typename std::enable_if<!std::is_void<F>::value, F>::type&& val);
+
+  template <class F = T,
+            typename std::enable_if<std::is_void<F>::value, int>::type = 0>
+  Future();
+
   ~Future();
 
   /** Return the reference to result. Should not be called if !isReady().
     Will rethrow the exception if an exception has been
     captured.
-
-    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();
@@ -190,9 +262,31 @@ class Future {
   /// 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 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"); });
 
@@ -204,180 +298,25 @@ class Future {
      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);
-
-  /// Variant where func takes a T directly, bypassing a try. Any exceptions
-  /// will be implicitly passed on to the resultant Future.
-  ///
-  ///   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.
-  ///
-  ///   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.
-  ///
-  ///   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,
-  ///
-  ///   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);
-
-  /// Variant where func is an ordinary function (static method, method)
-  ///
-  ///   R doWork(Try<T>&&);
-  ///
-  ///   Future<R> f2 = f1.then(doWork);
-  ///
-  /// or
-  ///
-  ///   struct Worker {
-  ///     static 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, 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));
-    });
+  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>&&); }
+  ///   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));
-    });
-  }
-
-  // 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.
+  ///   Future<R> f2 = f1.then(&Worker::doWork, w);
   ///
-  ///   struct Worker {
-  ///     Future<R> doWork(Try<T>&&); }
+  /// This is just sugar for
   ///
-  ///   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));
-    });
-  }
+  ///   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);
 
   /// Convenience method for ignoring the value and creating a Future<void>.
   /// Exceptions still propagate.
@@ -410,6 +349,29 @@ class Future {
     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:
+  ///
+  ///   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
@@ -478,7 +440,35 @@ class Future {
   /// now. The optional Timekeeper is as with futures::sleep().
   Future<T> delayed(Duration, Timekeeper* = nullptr);
 
- private:
+  /// 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>&);
+
+ protected:
   typedef detail::Core<T>* corePtr;
 
   // shared core state object
@@ -492,6 +482,22 @@ class Future {
   void throwIfInvalid() const;
 
   friend class Promise<T>;
+  template <class> friend class Future;
+
+  // 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) { core_->setExecutor(x); }
 };
 
 /**
@@ -565,8 +571,10 @@ Future<void> via(Executor* executor);
   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.
+  This function is thread-safe for Futures running on different threads. But
+  if you are doing anything non-trivial after, you will probably want to
+  follow with `via(executor)` because it will complete in whichever thread the
+  last Future completes in.
 
   The return type for Future<T> input is a Future<std::vector<Try<T>>>
   */
@@ -608,24 +616,6 @@ Future<std::vector<std::pair<
   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);
-
-/** 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);
-
 } // folly
 
 #include <folly/futures/Future-inl.h>