Do not construct a Future<T> from a Future<Something> value
[folly.git] / folly / futures / Future.h
index a14d62cfd89cb788be10fb1d889c00dc9cbae64c..06572c6306fc4818bfbfd5ff5966af8d5667b2c2 100644 (file)
 #include <folly/futures/FutureException.h>
 #include <folly/futures/detail/Types.h>
 
-namespace folly {
-
-template <class> struct Promise;
-
-template <typename T>
-struct isFuture : std::false_type {
-  typedef T Inner;
-};
-
-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 isTry<Try<T>> : std::true_type {};
+// boring predeclarations and details
+#include <folly/futures/Future-pre.h>
 
-namespace detail {
+// 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>
 
-template <class> struct Core;
-template <class...> struct VariadicContext;
-template <class> struct CollectContext;
-
-template<typename F, typename... Args>
-using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
-
-template <typename...>
-struct ArgType;
-
-template <typename Arg, typename... Args>
-struct ArgType<Arg, Args...> {
-  typedef Arg FirstArg;
-};
-
-template <>
-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, T&&>::value,
-      detail::argResult<false, F, T&&>,
-      typename std::conditional<
-        callableWith<F, T&>::value,
-        detail::argResult<false, F, T&>,
-        typename std::conditional<
-          callableWith<F, Try<T>&&>::value,
-          detail::argResult<true, F, Try<T>&&>,
-          detail::argResult<true, F, Try<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 Future<typename ReturnsFuture::Inner> Return;
-  typedef typename ReturnsFuture::Inner RawReturn;
-  typedef typename ArgType<Args...>::FirstArg FirstArg;
-};
-
-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;
-};
-
-} // detail
-
-struct Timekeeper;
-
-/// 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);
-
-  /// 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);
-
-  /**
-   * Set func as the callback for each input Future and return a vector of
-   * Futures containing the results in the input order.
-   */
-  template <class It, class F,
-            class ItT = typename std::iterator_traits<It>::value_type,
-            class Result = decltype(std::declval<ItT>().then(std::declval<F>()))>
-  std::vector<Future<Result>> map(It first, It last, F func);
-
-  // Sugar for the most common case
-  template <class Collection, class F>
-  auto map(Collection&& c, F&& func)
-      -> decltype(map(c.begin(), c.end(), func)) {
-    return map(c.begin(), c.end(), std::forward<F>(func));
-  }
-
-}
+namespace folly {
 
 template <class T>
 class Future {
@@ -213,17 +54,16 @@ class Future {
   Future(Future&&) noexcept;
   Future& operator=(Future&&) noexcept;
 
-  // makeFuture
-  template <class F = T>
+  /// Construct a Future from a value (perfect forwarding)
   /* 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>
+  template <class T2 = T,
+            typename std::enable_if<!isFuture<T2>::value, void*>::type = nullptr>
+  Future(T2&& val);
+
+  template <class T2 = T,
+            typename std::enable_if<
+              folly::is_void_or_unit<T2>::value,
+              int>::type = 0>
   Future();
 
   ~Future();
@@ -567,192 +407,6 @@ class Future {
   void setExecutor(Executor* x) { core_->setExecutor(x); }
 };
 
-/**
-  Make a completed Future by moving in a value. e.g.
-
-    string foo = "foo";
-    auto f = makeFuture(std::move(foo));
-
-  or
-
-    auto f = makeFuture<string>("foo");
-*/
-template <class T>
-Future<typename std::decay<T>::type> makeFuture(T&& t);
-
-/** Make a completed void Future. */
-Future<void> makeFuture();
-
-/** 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;
-
-/// Make a failed Future from an exception_wrapper.
-template <class T>
-Future<T> makeFuture(exception_wrapper ew);
-
-/** 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);
-
-/** Make a Future out of a Try */
-template <class T>
-Future<T> makeFuture(Try<T>&& t);
-
-/*
- * 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.
-
-  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>>>
-  */
-template <class InputIterator>
-Future<std::vector<Try<
-  typename std::iterator_traits<InputIterator>::value_type::value_type>>>
-collectAll(InputIterator first, InputIterator last);
-
-// Sugar for the most common case
-template <class Collection>
-auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
-  return collectAll(c.begin(), c.end());
-}
-
-/// 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
-collectAll(Fs&&... fs);
-
-/// Like collectAll, but will short circuit on the first exception. Thus, the
-/// type of the returned Future is std::vector<T> instead of
-/// std::vector<Try<T>>
-template <class InputIterator>
-Future<typename detail::CollectContext<
-  typename std::iterator_traits<InputIterator>::value_type::value_type
->::result_type>
-collect(InputIterator first, InputIterator last);
-
-// Sugar for the most common case
-template <class Collection>
-auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
-  return collect(c.begin(), c.end());
-}
-
-/** 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>>>
-collectAny(InputIterator first, InputIterator last);
-
-// Sugar for the most common case
-template <class Collection>
-auto collectAny(Collection&& c) -> decltype(collectAny(c.begin(), c.end())) {
-  return collectAny(c.begin(), c.end());
-}
-
-/** 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>>>>
-collectN(InputIterator first, InputIterator last, size_t n);
-
-// Sugar for the most common case
-template <class Collection>
-auto collectN(Collection&& c, size_t n)
-    -> decltype(collectN(c.begin(), c.end(), n)) {
-  return collectN(c.begin(), c.end(), n);
-}
-
-template <typename F, typename T, typename ItT>
-using MaybeTryArg = typename std::conditional<
-  detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type;
-
-template<typename F, typename T, typename Arg>
-using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;
-
-/** repeatedly calls func on every result, e.g.
-    reduce(reduce(reduce(T initial, result of first), result of second), ...)
-
-    The type of the final result is a Future of the type of the initial value.
-
-    Func can either return a T, or a Future<T>
-  */
-template <class It, class T, class F,
-          class ItT = typename std::iterator_traits<It>::value_type::value_type,
-          class Arg = MaybeTryArg<F, T, ItT>>
-typename std::enable_if<!isFutureResult<F, T, Arg>::value, Future<T>>::type
-reduce(It first, It last, T initial, F func);
-
-template <class It, class T, class F,
-          class ItT = typename std::iterator_traits<It>::value_type::value_type,
-          class Arg = MaybeTryArg<F, T, ItT>>
-typename std::enable_if<isFutureResult<F, T, Arg>::value, Future<T>>::type
-reduce(It first, It last, T initial, F func);
-
-// Sugar for the most common case
-template <class Collection, class T, class F>
-auto reduce(Collection&& c, T&& initial, F&& func)
-    -> decltype(reduce(c.begin(), c.end(), initial, func)) {
-  return reduce(
-      c.begin(),
-      c.end(),
-      std::forward<T>(initial),
-      std::forward<F>(func));
-}
 
 } // folly