Construct Later with exception_ptr
[folly.git] / folly / wangle / Future.h
index f20ef40965d6da4d42cabf0ba897bf909e12c0a7..0e99bb6ac9c4506d6be31828f0d3564057ea1370 100644 (file)
@@ -23,7 +23,7 @@
 #include <type_traits>
 #include <vector>
 
-#include "folly/MoveWrapper.h"
+#include <folly/MoveWrapper.h>
 #include "Promise.h"
 #include "Try.h"
 
@@ -41,7 +41,7 @@ class Future {
   Future& operator=(Future const&) = delete;
 
   // movable
-  Future(Future&&);
+  Future(Future&&) noexcept;
   Future& operator=(Future&&);
 
   ~Future();
@@ -59,40 +59,28 @@ class Future {
   typename std::add_lvalue_reference<const T>::type
   value() const;
 
-  /// Returns a future which will call back on the other side of executor.
+  /// Returns an inactive Future which will call back on the other side of
+  /// executor (when it is activated).
   ///
-  ///   f.via(e).then(a); // safe
+  /// NB remember that Futures activate when they destruct. This is good,
+  /// it means that this will work:
   ///
-  ///   f.via(e).then(a).then(b); // faux pas
+  ///   f.via(e).then(a).then(b);
   ///
-  /// a will definitely execute in the intended thread, but b may execute
-  /// either in that thread, or in the current thread. If you need to
-  /// guarantee where b executes, use a Later.
+  /// 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);
+  ///
+  /// If you need something like that, use a Later.
   template <typename Executor>
   Future<T> via(Executor* executor);
 
-  /// Deprecated alias for via
-  template <typename Executor>
-  Future<T> executeWithSameThread(Executor* executor) {
-    return via(executor);
-  }
-
-  /**
-     Thread-safe version of executeWith
-
-     Since an executor would likely start executing the Future chain
-     right away, it would be a race condition to call:
-     Future.executeWith(...).then(...), as there would be race
-     condition between the then and the running Future.
-     Instead, you may pass in a Promise so that we can set up
-     the rest of the chain in advance, without any racey
-     modifications of the continuation
-
-     Deprecated. Use a Later.
-   */
-  template <typename Executor>
-  void executeWith(Executor* executor, Promise<T>&& cont_promise);
-
   /** True when the result (or exception) is ready. */
   bool isReady() const;
 
@@ -110,8 +98,9 @@ class Future {
     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 probably want to support a similar API (instead of
-     executeWith). */
+     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,
@@ -196,19 +185,36 @@ class Future {
   /// Exceptions still propagate.
   Future<void> then();
 
-  /// Use of this method is advanced wizardry.
-  /// XXX should this be protected?
+  /// 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 setContinuation(F&& func);
+  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.
+  void activate() {
+    state_->activate();
+  }
+  void deactivate() {
+    state_->deactivate();
+  }
 
  private:
-  typedef detail::FutureObject<T>* objPtr;
+  typedef detail::State<T>* statePtr;
 
   // shared state object
-  objPtr obj_;
+  statePtr state_;
 
   explicit
-  Future(objPtr obj) : obj_(obj) {}
+  Future(statePtr obj) : state_(obj) {}
+
+  void detach();
 
   void throwIfInvalid() const;
 
@@ -313,6 +319,24 @@ 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 Duration>
+Future<T> waitWithSemaphore(Future<T>&& f, Duration timeout);
+
 }} // folly::wangle
 
 #include "Future-inl.h"