Commit 998b419a authored by Dave Watson's avatar Dave Watson

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
parent 5e80856a
...@@ -215,8 +215,8 @@ EventBase::~EventBase() { ...@@ -215,8 +215,8 @@ EventBase::~EventBase() {
delete timeout; delete timeout;
} }
while (!noWaitLoopCallbacks_.empty()) { while (!runBeforeLoopCallbacks_.empty()) {
delete &noWaitLoopCallbacks_.front(); delete &runBeforeLoopCallbacks_.front();
} }
(void) runLoopCallbacks(false); (void) runLoopCallbacks(false);
...@@ -299,18 +299,19 @@ bool EventBase::loopBody(int flags) { ...@@ -299,18 +299,19 @@ bool EventBase::loopBody(int flags) {
while (!stop_) { while (!stop_) {
++nextLoopCnt_; ++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 // nobody can add loop callbacks from within this thread if
// we don't have to handle anything to start with... // we don't have to handle anything to start with...
if (blocking && loopCallbacks_.empty()) { 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); res = event_base_loop(evb_, EVLOOP_ONCE);
} else { } else {
res = event_base_loop(evb_, EVLOOP_ONCE | EVLOOP_NONBLOCK); res = event_base_loop(evb_, EVLOOP_ONCE | EVLOOP_NONBLOCK);
...@@ -499,7 +500,7 @@ void EventBase::runOnDestruction(LoopCallback* callback) { ...@@ -499,7 +500,7 @@ void EventBase::runOnDestruction(LoopCallback* callback) {
void EventBase::runBeforeLoop(LoopCallback* callback) { void EventBase::runBeforeLoop(LoopCallback* callback) {
DCHECK(isInEventBaseThread()); DCHECK(isInEventBaseThread());
callback->cancelLoopCallback(); callback->cancelLoopCallback();
noWaitLoopCallbacks_.push_back(*callback); runBeforeLoopCallbacks_.push_back(*callback);
} }
bool EventBase::runInEventBaseThread(void (*fn)(void*), void* arg) { bool EventBase::runInEventBaseThread(void (*fn)(void*), void* arg) {
......
...@@ -262,6 +262,11 @@ class EventBase : ...@@ -262,6 +262,11 @@ class EventBase :
*/ */
void runOnDestruction(LoopCallback* callback); 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); void runBeforeLoop(LoopCallback* callback);
/** /**
...@@ -531,7 +536,7 @@ class EventBase : ...@@ -531,7 +536,7 @@ class EventBase :
CobTimeout::List pendingCobTimeouts_; CobTimeout::List pendingCobTimeouts_;
LoopCallbackList loopCallbacks_; LoopCallbackList loopCallbacks_;
LoopCallbackList noWaitLoopCallbacks_; LoopCallbackList runBeforeLoopCallbacks_;
LoopCallbackList onDestructionCallbacks_; LoopCallbackList onDestructionCallbacks_;
// This will be null most of the time, but point to currentCallbacks // This will be null most of the time, but point to currentCallbacks
......
...@@ -1540,3 +1540,26 @@ TEST(EventBaseTest, EventBaseThreadName) { ...@@ -1540,3 +1540,26 @@ TEST(EventBaseTest, EventBaseThreadName) {
ASSERT_EQ(0, strcmp("foo", name)); ASSERT_EQ(0, strcmp("foo", name));
#endif #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);
}
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