From: Scott Michelson Date: Thu, 30 Jun 2016 00:57:13 +0000 (-0700) Subject: Give each eventbase a wheeltimer X-Git-Tag: 2016.07.26~107 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=75e5507cbfe7ef5a448375e9908e10864b506b05;p=folly.git Give each eventbase a wheeltimer Summary: This gives each eventbase a wheeltimer. Construction is on demand, so there's no penalty if it isn't used. Why do this? 3 immediate reasons: 1) some clients already do this outside of the interface: diffusion/FBS/browse/master/fbcode/servicerouter/client/common/ThriftDispatcher.h$302,607?view=highlighted 2) inefficient timers can be easily avoided: diffusion/FBS/browse/master/fbcode/thrift/lib/cpp2/async/HeaderClientChannel.h;64fb260ea4bd235ba79414a78002fd68cf0453a8$319 3) D2379210 indicates we can do a better job with this than cob timeout Reviewed By: andriigrynenko, djwatson Differential Revision: D3460792 fbshipit-source-id: a7bb6fdd90ca95b6aef8af952d7a66dd0dc260c1 --- diff --git a/folly/io/async/EventBase.h b/folly/io/async/EventBase.h index 89e89fd1..507e8beb 100644 --- a/folly/io/async/EventBase.h +++ b/folly/io/async/EventBase.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -493,6 +494,13 @@ class EventBase : private boost::noncopyable, loopThread_.load(std::memory_order_relaxed), pthread_self()); } + HHWheelTimer& timer() { + if (!wheelTimer_) { + wheelTimer_ = HHWheelTimer::newTimer(this, std::chrono::milliseconds(1)); + } + return *wheelTimer_.get(); + } + // --------- interface to underlying libevent base ------------ // Avoid using these functions if possible. These functions are not // guaranteed to always be present if we ever provide alternative EventBase @@ -665,6 +673,9 @@ class EventBase : private boost::noncopyable, void initNotificationQueue(); + // should only be accessed through public getter + HHWheelTimer::UniquePtr wheelTimer_; + CobTimeout::List pendingCobTimeouts_; LoopCallbackList loopCallbacks_; diff --git a/folly/io/async/test/HHWheelTimerTest.cpp b/folly/io/async/test/HHWheelTimerTest.cpp index 90b260be..85ce3e83 100644 --- a/folly/io/async/test/HHWheelTimerTest.cpp +++ b/folly/io/async/test/HHWheelTimerTest.cpp @@ -110,7 +110,7 @@ TEST_F(HHWheelTimerTest, FireOnce) { * Test scheduling a timeout from another timeout callback. */ TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) { - StackWheelTimer t(&eventBase, milliseconds(10)); + HHWheelTimer& t = eventBase.timer(); TestTimeout t1; // Delayed to simulate the steady_clock counter lagging @@ -135,7 +135,7 @@ TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) { */ TEST_F(HHWheelTimerTest, CancelTimeout) { - StackWheelTimer t(&eventBase, milliseconds(1)); + HHWheelTimer& t = eventBase.timer(); // Create several timeouts that will all fire in 5ms. TestTimeout t5_1(&t, milliseconds(5)); @@ -350,7 +350,7 @@ TEST_F(HHWheelTimerTest, AtMostEveryN) { */ TEST_F(HHWheelTimerTest, SlowLoop) { - StackWheelTimer t(&eventBase, milliseconds(1)); + HHWheelTimer& t = eventBase.timer(); TestTimeout t1; TestTimeout t2; @@ -429,7 +429,7 @@ TEST_F(HHWheelTimerTest, DefaultTimeout) { } TEST_F(HHWheelTimerTest, lambda) { - StackWheelTimer t(&eventBase, milliseconds(1)); + HHWheelTimer& t = eventBase.timer(); size_t count = 0; t.scheduleTimeoutFn([&]{ count++; }, milliseconds(1)); eventBase.loop(); @@ -439,14 +439,14 @@ TEST_F(HHWheelTimerTest, lambda) { // 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)); + HHWheelTimer& t = eventBase.timer(); t.scheduleTimeoutFn([&]{ throw std::runtime_error("expected"); }, milliseconds(1)); eventBase.loop(); } TEST_F(HHWheelTimerTest, cancelAll) { - StackWheelTimer t(&eventBase); + HHWheelTimer& t = eventBase.timer(); TestTimeout tt; t.scheduleTimeout(&tt, std::chrono::minutes(1)); EXPECT_EQ(1, t.cancelAll());