From 11329181d7d5a98a5c71a483987a6185ec99e841 Mon Sep 17 00:00:00 2001 From: Hans Fugal Date: Fri, 5 Dec 2014 09:29:04 -0800 Subject: [PATCH] HHWheelTimer::scheduleTimeoutFn 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 | 19 ++++++++++++ folly/io/async/test/HHWheelTimerTest.cpp | 39 ++++++++++++++++-------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/folly/io/async/HHWheelTimer.h b/folly/io/async/HHWheelTimer.h index c0c1f8bf..eff837e5 100644 --- a/folly/io/async/HHWheelTimer.h +++ b/folly/io/async/HHWheelTimer.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -176,6 +177,24 @@ class HHWheelTimer : private folly::AsyncTimeout, void scheduleTimeoutImpl(Callback* callback, std::chrono::milliseconds timeout); + template + 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 */ diff --git a/folly/io/async/test/HHWheelTimerTest.cpp b/folly/io/async/test/HHWheelTimerTest.cpp index ddc9b4e6..3193926f 100644 --- a/folly/io/async/test/HHWheelTimerTest.cpp +++ b/folly/io/async/test/HHWheelTimerTest.cpp @@ -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(); +} -- 2.34.1