make io::Cursor::push() safe to call with an empty ByteRange
[folly.git] / folly / futures / ManualExecutor.h
index e1e38cd99acf8af21e749ed24fecbf244cc70ec0..76847e2cce496741d473469c38d83a278d33dbd8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,9 +15,9 @@
  */
 
 #pragma once
+#include <folly/LifoSem.h>
 #include <folly/futures/DrivableExecutor.h>
 #include <folly/futures/ScheduledExecutor.h>
-#include <semaphore.h>
 #include <memory>
 #include <mutex>
 #include <queue>
@@ -35,8 +35,6 @@ namespace folly {
   class ManualExecutor : public DrivableExecutor,
                          public ScheduledExecutor {
    public:
-    ManualExecutor();
-
     void add(Func) override;
 
     /// Do work. Returns the number of functions that were executed (maybe 0).
@@ -75,10 +73,10 @@ namespace folly {
 
     }
 
-    virtual void scheduleAt(Func&& f, TimePoint const& t) override {
+    void scheduleAt(Func&& f, TimePoint const& t) override {
       std::lock_guard<std::mutex> lock(lock_);
       scheduledFuncs_.emplace(t, std::move(f));
-      sem_post(&sem_);
+      sem_.post();
     }
 
     /// Advance the clock. The clock never advances on its own.
@@ -95,17 +93,32 @@ namespace folly {
 
     TimePoint now() override { return now_; }
 
+    /// Flush the function queue. Destroys all stored functions without
+    /// executing them. Returns number of removed functions.
+    std::size_t clear() {
+      std::queue<Func> funcs;
+      std::priority_queue<ScheduledFunc> scheduled_funcs;
+
+      {
+        std::lock_guard<std::mutex> lock(lock_);
+        funcs_.swap(funcs);
+        scheduledFuncs_.swap(scheduled_funcs);
+      }
+
+      return funcs.size() + scheduled_funcs.size();
+    }
+
    private:
     std::mutex lock_;
     std::queue<Func> funcs_;
-    sem_t sem_;
+    LifoSem sem_;
 
     // helper class to enable ordering of scheduled events in the priority
     // queue
     struct ScheduledFunc {
       TimePoint time;
       size_t ordinal;
-      Func func;
+      Func mutable func;
 
       ScheduledFunc(TimePoint const& t, Func&& f)
         : time(t), func(std::move(f))
@@ -115,13 +128,19 @@ namespace folly {
       }
 
       bool operator<(ScheduledFunc const& b) const {
+        // Earlier-scheduled things must be *higher* priority
+        // in the max-based std::priority_queue
         if (time == b.time)
-          return ordinal < b.ordinal;
-        return time < b.time;
+          return ordinal > b.ordinal;
+        return time > b.time;
+      }
+
+      Func&& moveOutFunc() const {
+        return std::move(func);
       }
     };
     std::priority_queue<ScheduledFunc> scheduledFuncs_;
-    TimePoint now_ = now_.min();
+    TimePoint now_ = TimePoint::min();
   };
 
 }