adding Promise::await
[folly.git] / folly / experimental / fibers / Baton.h
index 49585d9ee999ad517ba5181daedebe4a959c0fde..c2ee7044fc9a59837de0111475678c217002ee4a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 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/detail/Futex.h>
 #include <folly/experimental/fibers/TimeoutController.h>
 
-namespace folly { namespace fibers {
+namespace folly {
+namespace fibers {
 
 class Fiber;
+class FiberManager;
 
 /**
  * @class Baton
  *
- * Primitive which allows to put current Fiber to sleep and wake it from another
- * Fiber/thread.
+ * Primitive which allows one to put current Fiber to sleep and wake it from
+ * another Fiber/thread.
  */
 class Baton {
  public:
+  class TimeoutHandler;
+
   Baton();
 
   ~Baton() {}
@@ -41,6 +45,15 @@ class Baton {
    */
   void wait();
 
+  /**
+   * Put active fiber to sleep indefinitely. However, timeoutHandler may
+   * be used elsewhere on the same thread in order to schedule a wakeup
+   * for the active fiber.  Users of timeoutHandler must be on the same thread
+   * as the active fiber and may only schedule one timeout, which must occur
+   * after the active fiber calls wait.
+   */
+  void wait(TimeoutHandler& timeoutHandler);
+
   /**
    * Puts active fiber to sleep. Returns when post is called.
    *
@@ -54,8 +67,8 @@ class Baton {
    * This is here only not break tao/locks. Please don't use it, because it is
    * inefficient when used on Fibers.
    */
-  template<typename C, typename D = typename C::duration>
-  bool timed_wait(const std::chrono::time_point<C,D>& timeout);
+  template <typename C, typename D = typename C::duration>
+  bool timed_wait(const std::chrono::time_point<C, D>& timeout);
 
   /**
    * Puts active fiber to sleep. Returns when post is called.
@@ -98,6 +111,29 @@ class Baton {
    */
   void reset();
 
+  /**
+   * Provides a way to schedule a wakeup for a wait()ing fiber.
+   * A TimeoutHandler must be passed to Baton::wait(TimeoutHandler&)
+   * before a timeout is scheduled. It is only safe to use the
+   * TimeoutHandler on the same thread as the wait()ing fiber.
+   * scheduleTimeout() may only be called once prior to the end of the
+   * associated Baton's life.
+   */
+  class TimeoutHandler {
+   public:
+    void scheduleTimeout(TimeoutController::Duration timeoutMs);
+
+   private:
+    friend class Baton;
+
+    void cancelTimeout();
+
+    std::function<void()> timeoutFunc_{nullptr};
+    FiberManager* fiberManager_{nullptr};
+
+    intptr_t timeoutPtr_{0};
+  };
+
  private:
   enum {
     /**
@@ -118,7 +154,7 @@ class Baton {
     PreBlockAttempts = 300,
   };
 
-  explicit Baton(intptr_t state) : waitingFiber_(state) {};
+  explicit Baton(intptr_t state) : waitingFiber_(state){};
 
   void postHelper(intptr_t new_value);
   void postThread();
@@ -149,7 +185,7 @@ class Baton {
     } futex_;
   };
 };
-
-}}
+}
+}
 
 #include <folly/experimental/fibers/Baton-inl.h>