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 @@
#include <folly/experimental/ExecutionObserver.h>
#include <folly/futures/DrivableExecutor.h>
#include <folly/io/async/AsyncTimeout.h>
#include <folly/io/async/HHWheelTimer.h>
#include <folly/io/async/Request.h>
#include <folly/io/async/TimeoutManager.h>
#include <folly/portability/PThread.h>
......@@ -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_;
......
......@@ -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());
......
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