Commit a7c4b5ba authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook GitHub Bot

Use AtomicNotificationQueue in EventBase

Differential Revision: D24414496

fbshipit-source-id: ad552d3dd58b6c351c99e5f8c9056c5829c4c095
parent 6d95d30f
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include <folly/Memory.h> #include <folly/Memory.h>
#include <folly/String.h> #include <folly/String.h>
#include <folly/io/async/AtomicNotificationQueue.h>
#include <folly/io/async/EventBaseBackendBase.h> #include <folly/io/async/EventBaseBackendBase.h>
#include <folly/io/async/NotificationQueue.h>
#include <folly/io/async/VirtualEventBase.h> #include <folly/io/async/VirtualEventBase.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#include <folly/synchronization/Baton.h> #include <folly/synchronization/Baton.h>
...@@ -131,15 +131,6 @@ EventBaseBackend::~EventBaseBackend() { ...@@ -131,15 +131,6 @@ EventBaseBackend::~EventBaseBackend() {
} // namespace } // namespace
namespace folly { namespace folly {
/*
* EventBase::FunctionRunner
*/
class EventBase::FunctionRunner
: public NotificationQueue<EventBase::Func>::Consumer {
public:
void messageAvailable(Func&& msg) noexcept override { msg(); }
};
/* /*
* EventBase methods * EventBase methods
...@@ -165,7 +156,6 @@ EventBase::EventBase(Options options) ...@@ -165,7 +156,6 @@ EventBase::EventBase(Options options)
stop_(false), stop_(false),
loopThread_(), loopThread_(),
queue_(nullptr), queue_(nullptr),
fnRunner_(nullptr),
maxLatency_(0), maxLatency_(0),
avgLoopTime_(std::chrono::seconds(2)), avgLoopTime_(std::chrono::seconds(2)),
maxLatencyLoopTime_(avgLoopTime_), maxLatencyLoopTime_(avgLoopTime_),
...@@ -218,12 +208,10 @@ EventBase::~EventBase() { ...@@ -218,12 +208,10 @@ EventBase::~EventBase() {
(void)runLoopCallbacks(); (void)runLoopCallbacks();
if (!fnRunner_->consumeUntilDrained()) { queue_->drain();
LOG(ERROR) << "~EventBase(): Unable to drain notification queue";
}
// Stop consumer before deleting NotificationQueue // Stop consumer before deleting NotificationQueue
fnRunner_->stopConsuming(); queue_->stopConsuming();
evb_.reset(); evb_.reset();
for (auto storage : localStorageToDtor_) { for (auto storage : localStorageToDtor_) {
...@@ -242,7 +230,7 @@ size_t EventBase::getNotificationQueueSize() const { ...@@ -242,7 +230,7 @@ size_t EventBase::getNotificationQueueSize() const {
} }
void EventBase::setMaxReadAtOnce(uint32_t maxAtOnce) { void EventBase::setMaxReadAtOnce(uint32_t maxAtOnce) {
fnRunner_->setMaxReadAtOnce(maxAtOnce); queue_->setMaxReadAtOnce(maxAtOnce);
} }
void EventBase::checkIsInEventBaseThread() const { void EventBase::checkIsInEventBaseThread() const {
...@@ -305,8 +293,8 @@ bool EventBase::loopIgnoreKeepAlive() { ...@@ -305,8 +293,8 @@ bool EventBase::loopIgnoreKeepAlive() {
if (loopKeepAliveActive_) { if (loopKeepAliveActive_) {
// Make sure NotificationQueue is not counted as one of the readers // Make sure NotificationQueue is not counted as one of the readers
// (otherwise loopBody won't return until terminateLoopSoon is called). // (otherwise loopBody won't return until terminateLoopSoon is called).
fnRunner_->stopConsuming(); queue_->stopConsuming();
fnRunner_->startConsumingInternal(this, queue_.get()); queue_->startConsumingInternal(this);
loopKeepAliveActive_ = false; loopKeepAliveActive_ = false;
} }
return loopBody(0, true); return loopBody(0, true);
...@@ -435,8 +423,8 @@ bool EventBase::loopBody(int flags, bool ignoreKeepAlive) { ...@@ -435,8 +423,8 @@ bool EventBase::loopBody(int flags, bool ignoreKeepAlive) {
// Since Notification Queue is marked 'internal' some events may not have // Since Notification Queue is marked 'internal' some events may not have
// run. Run them manually if so, and continue looping. // run. Run them manually if so, and continue looping.
// //
if (getNotificationQueueSize() > 0) { if (!queue_->empty()) {
fnRunner_->handlerReady(0); queue_->execute();
} else if (!ranLoopCallbacks) { } else if (!ranLoopCallbacks) {
// If there were no more events and we also didn't have any loop // If there were no more events and we also didn't have any loop
// callbacks to run, there is nothing left to do. // callbacks to run, there is nothing left to do.
...@@ -493,15 +481,15 @@ void EventBase::applyLoopKeepAlive() { ...@@ -493,15 +481,15 @@ void EventBase::applyLoopKeepAlive() {
if (loopKeepAliveActive_ && keepAliveCount == 0) { if (loopKeepAliveActive_ && keepAliveCount == 0) {
// Restore the notification queue internal flag // Restore the notification queue internal flag
fnRunner_->stopConsuming(); queue_->stopConsuming();
fnRunner_->startConsumingInternal(this, queue_.get()); queue_->startConsumingInternal(this);
loopKeepAliveActive_ = false; loopKeepAliveActive_ = false;
} else if (!loopKeepAliveActive_ && keepAliveCount > 0) { } else if (!loopKeepAliveActive_ && keepAliveCount > 0) {
// Update the notification queue event to treat it as a normal // Update the notification queue event to treat it as a normal
// (non-internal) event. The notification queue event always remains // (non-internal) event. The notification queue event always remains
// installed, and the main loop won't exit with it installed. // installed, and the main loop won't exit with it installed.
fnRunner_->stopConsuming(); queue_->stopConsuming();
fnRunner_->startConsuming(this, queue_.get()); queue_->startConsuming(this);
loopKeepAliveActive_ = true; loopKeepAliveActive_ = true;
} }
} }
...@@ -692,12 +680,7 @@ bool EventBase::runLoopCallbacks() { ...@@ -692,12 +680,7 @@ bool EventBase::runLoopCallbacks() {
void EventBase::initNotificationQueue() { void EventBase::initNotificationQueue() {
// Infinite size queue // Infinite size queue
queue_ = std::make_unique<NotificationQueue<Func>>(); queue_ = std::make_unique<AtomicNotificationQueue>();
// We allocate fnRunner_ separately, rather than declaring it directly
// as a member of EventBase solely so that we don't need to include
// NotificationQueue.h from EventBase.h
fnRunner_ = std::make_unique<FunctionRunner>();
// Mark this as an internal event, so event_base_loop() will return if // Mark this as an internal event, so event_base_loop() will return if
// there are no other events besides this one installed. // there are no other events besides this one installed.
...@@ -708,7 +691,7 @@ void EventBase::initNotificationQueue() { ...@@ -708,7 +691,7 @@ void EventBase::initNotificationQueue() {
// Users can use loopForever() if they do care about the notification queue. // Users can use loopForever() if they do care about the notification queue.
// (This is useful for EventBase threads that do nothing but process // (This is useful for EventBase threads that do nothing but process
// runInEventBaseThread() notifications.) // runInEventBaseThread() notifications.)
fnRunner_->startConsumingInternal(this, queue_.get()); queue_->startConsumingInternal(this);
} }
void EventBase::SmoothLoopTime::setTimeInterval( void EventBase::SmoothLoopTime::setTimeInterval(
......
...@@ -55,6 +55,7 @@ class EventBaseBackendBase; ...@@ -55,6 +55,7 @@ class EventBaseBackendBase;
using Cob = Func; // defined in folly/Executor.h using Cob = Func; // defined in folly/Executor.h
class AtomicNotificationQueue;
template <typename MessageT> template <typename MessageT>
class NotificationQueue; class NotificationQueue;
...@@ -865,7 +866,6 @@ class EventBase : public TimeoutManager, ...@@ -865,7 +866,6 @@ class EventBase : public TimeoutManager,
bool nothingHandledYet() const noexcept; bool nothingHandledYet() const noexcept;
typedef LoopCallback::List LoopCallbackList; typedef LoopCallback::List LoopCallbackList;
class FunctionRunner;
bool loopBody(int flags = 0, bool ignoreKeepAlive = false); bool loopBody(int flags = 0, bool ignoreKeepAlive = false);
...@@ -900,8 +900,7 @@ class EventBase : public TimeoutManager, ...@@ -900,8 +900,7 @@ class EventBase : public TimeoutManager,
// A notification queue for runInEventBaseThread() to use // A notification queue for runInEventBaseThread() to use
// to send function requests to the EventBase thread. // to send function requests to the EventBase thread.
std::unique_ptr<NotificationQueue<Func>> queue_; std::unique_ptr<AtomicNotificationQueue> queue_;
std::unique_ptr<FunctionRunner> fnRunner_;
ssize_t loopKeepAliveCount_{0}; ssize_t loopKeepAliveCount_{0};
std::atomic<ssize_t> loopKeepAliveCountAtomic_{0}; std::atomic<ssize_t> loopKeepAliveCountAtomic_{0};
bool loopKeepAliveActive_{false}; bool loopKeepAliveActive_{false};
......
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