From: Dave Watson Date: Thu, 13 Nov 2014 20:51:43 +0000 (-0800) Subject: Clean up runBeforeLoop API X-Git-Tag: v0.22.0~163 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=998b419afe824049bf539699ca1968648db13e18;p=folly.git Clean up runBeforeLoop API Summary: Clean up API per stepan's comments in D1641057: runBeforeLoop callbacks should be run before the if block, so runInLoop calls will work. Test Plan: added unittest Reviewed By: hans@fb.com Subscribers: trunkagent, doug, alandau, bmatheny, njormrod, mshneer, folly-diffs@ FB internal diff: D1679773 Signature: t1:1679773:1415916488:f20dd98bf40dd4cb19a4b11875dc0c9fa3e7870e Blame Revision: D1641057 --- diff --git a/folly/io/async/EventBase.cpp b/folly/io/async/EventBase.cpp index 0e34c5e2..6916ceac 100644 --- a/folly/io/async/EventBase.cpp +++ b/folly/io/async/EventBase.cpp @@ -215,8 +215,8 @@ EventBase::~EventBase() { delete timeout; } - while (!noWaitLoopCallbacks_.empty()) { - delete &noWaitLoopCallbacks_.front(); + while (!runBeforeLoopCallbacks_.empty()) { + delete &runBeforeLoopCallbacks_.front(); } (void) runLoopCallbacks(false); @@ -299,18 +299,19 @@ bool EventBase::loopBody(int flags) { while (!stop_) { ++nextLoopCnt_; + // Run the before loop callbacks + LoopCallbackList callbacks; + callbacks.swap(runBeforeLoopCallbacks_); + + while(!callbacks.empty()) { + auto* item = &callbacks.front(); + callbacks.pop_front(); + item->runLoopCallback(); + } + // nobody can add loop callbacks from within this thread if // we don't have to handle anything to start with... if (blocking && loopCallbacks_.empty()) { - LoopCallbackList callbacks; - callbacks.swap(noWaitLoopCallbacks_); - - while(!callbacks.empty()) { - auto* item = &callbacks.front(); - callbacks.pop_front(); - item->runLoopCallback(); - } - res = event_base_loop(evb_, EVLOOP_ONCE); } else { res = event_base_loop(evb_, EVLOOP_ONCE | EVLOOP_NONBLOCK); @@ -499,7 +500,7 @@ void EventBase::runOnDestruction(LoopCallback* callback) { void EventBase::runBeforeLoop(LoopCallback* callback) { DCHECK(isInEventBaseThread()); callback->cancelLoopCallback(); - noWaitLoopCallbacks_.push_back(*callback); + runBeforeLoopCallbacks_.push_back(*callback); } bool EventBase::runInEventBaseThread(void (*fn)(void*), void* arg) { diff --git a/folly/io/async/EventBase.h b/folly/io/async/EventBase.h index 3da2169d..d1846071 100644 --- a/folly/io/async/EventBase.h +++ b/folly/io/async/EventBase.h @@ -262,6 +262,11 @@ class EventBase : */ void runOnDestruction(LoopCallback* callback); + /** + * Adds a callback that will run immediately *before* the event loop. + * This is very similar to runInLoop(), but will not cause the loop to break: + * For example, this callback could be used to get loop times. + */ void runBeforeLoop(LoopCallback* callback); /** @@ -531,7 +536,7 @@ class EventBase : CobTimeout::List pendingCobTimeouts_; LoopCallbackList loopCallbacks_; - LoopCallbackList noWaitLoopCallbacks_; + LoopCallbackList runBeforeLoopCallbacks_; LoopCallbackList onDestructionCallbacks_; // This will be null most of the time, but point to currentCallbacks diff --git a/folly/io/async/test/EventBaseTest.cpp b/folly/io/async/test/EventBaseTest.cpp index ddf70a06..3dab11d7 100644 --- a/folly/io/async/test/EventBaseTest.cpp +++ b/folly/io/async/test/EventBaseTest.cpp @@ -1540,3 +1540,26 @@ TEST(EventBaseTest, EventBaseThreadName) { ASSERT_EQ(0, strcmp("foo", name)); #endif } + +TEST(TEventBaseTest, RunBeforeLoop) { + TEventBase base; + CountedLoopCallback cb(&base, 1, [&](){ + base.terminateLoopSoon(); + }); + base.runBeforeLoop(&cb); + base.loopForever(); + ASSERT_EQUAL(cb.getCount(), 0); +} + +TEST(TEventBaseTest, RunBeforeLoopWait) { + TEventBase base; + CountedLoopCallback cb(&base, 1); + base.runAfterDelay([&](){ + base.terminateLoopSoon(); + }, 500); + base.runBeforeLoop(&cb); + base.loopForever(); + + // Check that we only ran once, and did not loop multiple times. + ASSERT_EQUAL(cb.getCount(), 0); +}