HHWheelTimer::scheduleTimeoutFn
authorHans Fugal <fugalh@fb.com>
Fri, 5 Dec 2014 17:29:04 +0000 (09:29 -0800)
committerDave Watson <davejwatson@fb.com>
Thu, 11 Dec 2014 16:00:46 +0000 (08:00 -0800)
Summary:
cpp11ify

I'm gonna use this for Wangle timeouts.

Test Plan:
new unit test
_bin/folly/io/async/test/HHWheelTimerTest

Reviewed By: jsedgwick@fb.com

Subscribers: trunkagent, exa, njormrod, folly-diffs@

FB internal diff: D1720014

Tasks: 5002969

Signature: t1:1720014:1417732753:ddcad431b6c305c9ba27f6b9e3454ab158c13f4b

folly/io/async/HHWheelTimer.h
folly/io/async/test/HHWheelTimerTest.cpp

index c0c1f8bf8865ea393dd173823133fe06d2fb2aef..eff837e5a645091525f78a43fafd75ff7497d50a 100644 (file)
@@ -20,6 +20,7 @@
 #include <folly/io/async/DelayedDestruction.h>
 
 #include <boost/intrusive/list.hpp>
+#include <glog/logging.h>
 
 #include <chrono>
 #include <cstddef>
@@ -176,6 +177,24 @@ class HHWheelTimer : private folly::AsyncTimeout,
   void scheduleTimeoutImpl(Callback* callback,
                        std::chrono::milliseconds timeout);
 
+  template <class F>
+  void scheduleTimeoutFn(F fn, std::chrono::milliseconds timeout) {
+    struct Wrapper : Callback {
+      Wrapper(F fn) : fn_(std::move(fn)) {}
+      void timeoutExpired() noexcept override {
+        try {
+          fn_();
+        } catch (std::exception const& e) {
+          LOG(ERROR) << e.what();
+        } catch (...) { }
+        delete this;
+      }
+      F fn_;
+    };
+    Wrapper* w = new Wrapper(std::move(fn));
+    scheduleTimeout(w, timeout);
+  }
+
   /**
    * Return the number of currently pending timeouts
    */
index ddc9b4e6b27db7d0f94a7fc0521f0253e286694f..3193926f591a671d1cb53ea0661cfaef00172c58 100644 (file)
@@ -56,11 +56,14 @@ class TestTimeoutDelayed : public TestTimeout {
     }
 };
 
+struct HHWheelTimerTest : public ::testing::Test {
+  EventBase eventBase;
+};
+
 /*
  * Test firing some simple timeouts that are fired once and never rescheduled
  */
-TEST(HHWheelTimerTest, FireOnce) {
-  EventBase eventBase;
+TEST_F(HHWheelTimerTest, FireOnce) {
   StackWheelTimer t(&eventBase, milliseconds(1));
 
   const HHWheelTimer::Callback* nullCallback = nullptr;
@@ -99,8 +102,7 @@ TEST(HHWheelTimerTest, FireOnce) {
 /*
  * Test scheduling a timeout from another timeout callback.
  */
-TEST(HHWheelTimerTest, TestSchedulingWithinCallback) {
-  EventBase eventBase;
+TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) {
   StackWheelTimer t(&eventBase, milliseconds(10));
   const HHWheelTimer::Callback* nullCallback = nullptr;
 
@@ -126,8 +128,7 @@ TEST(HHWheelTimerTest, TestSchedulingWithinCallback) {
  * Test cancelling a timeout when it is scheduled to be fired right away.
  */
 
-TEST(HHWheelTimerTest, CancelTimeout) {
-  EventBase eventBase;
+TEST_F(HHWheelTimerTest, CancelTimeout) {
   StackWheelTimer t(&eventBase, milliseconds(1));
 
   // Create several timeouts that will all fire in 5ms.
@@ -208,8 +209,7 @@ TEST(HHWheelTimerTest, CancelTimeout) {
  * Test destroying a HHWheelTimer with timeouts outstanding
  */
 
-TEST(HHWheelTimerTest, DestroyTimeoutSet) {
-  EventBase eventBase;
+TEST_F(HHWheelTimerTest, DestroyTimeoutSet) {
 
   HHWheelTimer::UniquePtr t(
     new HHWheelTimer(&eventBase, milliseconds(1)));
@@ -250,8 +250,7 @@ TEST(HHWheelTimerTest, DestroyTimeoutSet) {
 /*
  * Test the tick interval parameter
  */
-TEST(HHWheelTimerTest, AtMostEveryN) {
-  EventBase eventBase;
+TEST_F(HHWheelTimerTest, AtMostEveryN) {
 
   // Create a timeout set with a 10ms interval, to fire no more than once
   // every 3ms.
@@ -337,8 +336,7 @@ TEST(HHWheelTimerTest, AtMostEveryN) {
  * Test an event loop that is blocking
  */
 
-TEST(HHWheelTimerTest, SlowLoop) {
-  EventBase eventBase;
+TEST_F(HHWheelTimerTest, SlowLoop) {
   StackWheelTimer t(&eventBase, milliseconds(1));
 
   TestTimeout t1;
@@ -381,3 +379,20 @@ TEST(HHWheelTimerTest, SlowLoop) {
   T_CHECK_TIMEOUT(start2, t2.timestamps[0], milliseconds(10), milliseconds(1));
   T_CHECK_TIMEOUT(start2, end2, milliseconds(10), milliseconds(1));
 }
+
+TEST_F(HHWheelTimerTest, lambda) {
+  StackWheelTimer t(&eventBase, milliseconds(1));
+  size_t count = 0;
+  t.scheduleTimeoutFn([&]{ count++; }, milliseconds(1));
+  eventBase.loop();
+  EXPECT_EQ(1, count);
+}
+
+// shouldn't crash because we swallow and log the error (you'll have to look
+// at the console to confirm logging)
+TEST_F(HHWheelTimerTest, lambdaThrows) {
+  StackWheelTimer t(&eventBase, milliseconds(1));
+  t.scheduleTimeoutFn([&]{ throw std::runtime_error("foo"); },
+                      milliseconds(1));
+  eventBase.loop();
+}