Commit 75e5507c authored by Scott Michelson's avatar Scott Michelson Committed by Facebook Github Bot 4

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
parent e6aa2684
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <folly/experimental/ExecutionObserver.h> #include <folly/experimental/ExecutionObserver.h>
#include <folly/futures/DrivableExecutor.h> #include <folly/futures/DrivableExecutor.h>
#include <folly/io/async/AsyncTimeout.h> #include <folly/io/async/AsyncTimeout.h>
#include <folly/io/async/HHWheelTimer.h>
#include <folly/io/async/Request.h> #include <folly/io/async/Request.h>
#include <folly/io/async/TimeoutManager.h> #include <folly/io/async/TimeoutManager.h>
#include <folly/portability/PThread.h> #include <folly/portability/PThread.h>
...@@ -493,6 +494,13 @@ class EventBase : private boost::noncopyable, ...@@ -493,6 +494,13 @@ class EventBase : private boost::noncopyable,
loopThread_.load(std::memory_order_relaxed), pthread_self()); 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 ------------ // --------- interface to underlying libevent base ------------
// Avoid using these functions if possible. These functions are not // Avoid using these functions if possible. These functions are not
// guaranteed to always be present if we ever provide alternative EventBase // guaranteed to always be present if we ever provide alternative EventBase
...@@ -665,6 +673,9 @@ class EventBase : private boost::noncopyable, ...@@ -665,6 +673,9 @@ class EventBase : private boost::noncopyable,
void initNotificationQueue(); void initNotificationQueue();
// should only be accessed through public getter
HHWheelTimer::UniquePtr wheelTimer_;
CobTimeout::List pendingCobTimeouts_; CobTimeout::List pendingCobTimeouts_;
LoopCallbackList loopCallbacks_; LoopCallbackList loopCallbacks_;
......
...@@ -110,7 +110,7 @@ TEST_F(HHWheelTimerTest, FireOnce) { ...@@ -110,7 +110,7 @@ TEST_F(HHWheelTimerTest, FireOnce) {
* Test scheduling a timeout from another timeout callback. * Test scheduling a timeout from another timeout callback.
*/ */
TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) { TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) {
StackWheelTimer t(&eventBase, milliseconds(10)); HHWheelTimer& t = eventBase.timer();
TestTimeout t1; TestTimeout t1;
// Delayed to simulate the steady_clock counter lagging // Delayed to simulate the steady_clock counter lagging
...@@ -135,7 +135,7 @@ TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) { ...@@ -135,7 +135,7 @@ TEST_F(HHWheelTimerTest, TestSchedulingWithinCallback) {
*/ */
TEST_F(HHWheelTimerTest, CancelTimeout) { TEST_F(HHWheelTimerTest, CancelTimeout) {
StackWheelTimer t(&eventBase, milliseconds(1)); HHWheelTimer& t = eventBase.timer();
// Create several timeouts that will all fire in 5ms. // Create several timeouts that will all fire in 5ms.
TestTimeout t5_1(&t, milliseconds(5)); TestTimeout t5_1(&t, milliseconds(5));
...@@ -350,7 +350,7 @@ TEST_F(HHWheelTimerTest, AtMostEveryN) { ...@@ -350,7 +350,7 @@ TEST_F(HHWheelTimerTest, AtMostEveryN) {
*/ */
TEST_F(HHWheelTimerTest, SlowLoop) { TEST_F(HHWheelTimerTest, SlowLoop) {
StackWheelTimer t(&eventBase, milliseconds(1)); HHWheelTimer& t = eventBase.timer();
TestTimeout t1; TestTimeout t1;
TestTimeout t2; TestTimeout t2;
...@@ -429,7 +429,7 @@ TEST_F(HHWheelTimerTest, DefaultTimeout) { ...@@ -429,7 +429,7 @@ TEST_F(HHWheelTimerTest, DefaultTimeout) {
} }
TEST_F(HHWheelTimerTest, lambda) { TEST_F(HHWheelTimerTest, lambda) {
StackWheelTimer t(&eventBase, milliseconds(1)); HHWheelTimer& t = eventBase.timer();
size_t count = 0; size_t count = 0;
t.scheduleTimeoutFn([&]{ count++; }, milliseconds(1)); t.scheduleTimeoutFn([&]{ count++; }, milliseconds(1));
eventBase.loop(); eventBase.loop();
...@@ -439,14 +439,14 @@ TEST_F(HHWheelTimerTest, lambda) { ...@@ -439,14 +439,14 @@ TEST_F(HHWheelTimerTest, lambda) {
// shouldn't crash because we swallow and log the error (you'll have to look // shouldn't crash because we swallow and log the error (you'll have to look
// at the console to confirm logging) // at the console to confirm logging)
TEST_F(HHWheelTimerTest, lambdaThrows) { TEST_F(HHWheelTimerTest, lambdaThrows) {
StackWheelTimer t(&eventBase, milliseconds(1)); HHWheelTimer& t = eventBase.timer();
t.scheduleTimeoutFn([&]{ throw std::runtime_error("expected"); }, t.scheduleTimeoutFn([&]{ throw std::runtime_error("expected"); },
milliseconds(1)); milliseconds(1));
eventBase.loop(); eventBase.loop();
} }
TEST_F(HHWheelTimerTest, cancelAll) { TEST_F(HHWheelTimerTest, cancelAll) {
StackWheelTimer t(&eventBase); HHWheelTimer& t = eventBase.timer();
TestTimeout tt; TestTimeout tt;
t.scheduleTimeout(&tt, std::chrono::minutes(1)); t.scheduleTimeout(&tt, std::chrono::minutes(1));
EXPECT_EQ(1, t.cancelAll()); EXPECT_EQ(1, t.cancelAll());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment