Commit 51e98fa7 authored by Yunqi Zhang's avatar Yunqi Zhang Committed by Anton Likhtarov

Expose EVLOOP_NONBLOCK

Summary:
This diff allows users to loop through EventBase without blocking if there are
not any events to process.

This is useful for sending and receiving requests on network, where users just
want to try if there are any events and do not want to block if not.

https://phabricator.fb.com/D1373887 is an example where we find this feature
useful, otherwise we have to add an empty callback before loop.
event_base_.runInLoop([] {});
event_base_.loopOnce();

@davejwatson, @fugalh, @simpkins, @stepan: Could you please take a look at the
proposed changes and let me know if there is any better ways of doing this.

Thank you!

Test Plan:
I think this would not break anything, but we might want to do some performance
profiling if needed.

Reviewed By: hans@fb.com

Subscribers: simpkins, davejwatson, fugalh, stepan, folly@lists

FB internal diff: D1383401
parent a97b3be5
...@@ -246,15 +246,16 @@ bool EventBase::loop() { ...@@ -246,15 +246,16 @@ bool EventBase::loop() {
return loopBody(); return loopBody();
} }
bool EventBase::loopOnce() { bool EventBase::loopOnce(int flags) {
return loopBody(true); return loopBody(flags | EVLOOP_ONCE);
} }
bool EventBase::loopBody(bool once) { bool EventBase::loopBody(int flags) {
VLOG(5) << "EventBase(): Starting loop."; VLOG(5) << "EventBase(): Starting loop.";
int res = 0; int res = 0;
bool ranLoopCallbacks; bool ranLoopCallbacks;
int nonBlocking; bool blocking = !(flags & EVLOOP_NONBLOCK);
bool once = (flags & EVLOOP_ONCE);
loopThread_.store(pthread_self(), std::memory_order_release); loopThread_.store(pthread_self(), std::memory_order_release);
...@@ -272,8 +273,11 @@ bool EventBase::loopBody(bool once) { ...@@ -272,8 +273,11 @@ bool EventBase::loopBody(bool once) {
// 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...
nonBlocking = (loopCallbacks_.empty() ? 0 : EVLOOP_NONBLOCK); if (blocking && loopCallbacks_.empty()) {
res = event_base_loop(evb_, EVLOOP_ONCE | nonBlocking); res = event_base_loop(evb_, EVLOOP_ONCE);
} else {
res = event_base_loop(evb_, EVLOOP_ONCE | EVLOOP_NONBLOCK);
}
ranLoopCallbacks = runLoopCallbacks(); ranLoopCallbacks = runLoopCallbacks();
int64_t busy = std::chrono::duration_cast<std::chrono::microseconds>( int64_t busy = std::chrono::duration_cast<std::chrono::microseconds>(
......
...@@ -146,11 +146,14 @@ class EventBase : private boost::noncopyable, public TimeoutManager { ...@@ -146,11 +146,14 @@ class EventBase : private boost::noncopyable, public TimeoutManager {
/** /**
* Wait for some events to become active, run them, then return. * Wait for some events to become active, run them, then return.
* *
* When EVLOOP_NONBLOCK is set in flags, the loop won't block if there
* are not any events to process.
*
* This is useful for callers that want to run the loop manually. * This is useful for callers that want to run the loop manually.
* *
* Returns the same result as loop(). * Returns the same result as loop().
*/ */
bool loopOnce(); bool loopOnce(int flags = 0);
/** /**
* Runs the event loop. * Runs the event loop.
...@@ -502,7 +505,7 @@ class EventBase : private boost::noncopyable, public TimeoutManager { ...@@ -502,7 +505,7 @@ class EventBase : private boost::noncopyable, public TimeoutManager {
typedef LoopCallback::List LoopCallbackList; typedef LoopCallback::List LoopCallbackList;
class FunctionRunner; class FunctionRunner;
bool loopBody(bool once = false); bool loopBody(int flags = 0);
// executes any callbacks queued by runInLoop(); returns false if none found // executes any callbacks queued by runInLoop(); returns false if none found
bool runLoopCallbacks(bool setContext = true); bool runLoopCallbacks(bool setContext = true);
......
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