From 234eb60546aa52d6bcae3f7a68c90d2e84b0b5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Tue, 14 Jan 2025 16:42:31 +0100 Subject: apps: common: event_loop: Use single event source for deferred calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of calling `event_base_once()` every time a deferred call is added to the loop, create an event source at construction, and simply trigger that when a new deferred call is scheduled. Signed-off-by: Barnabás Pőcze Reviewed-by: Jacopo Mondi --- src/apps/common/event_loop.cpp | 48 +++++++++++++++++++++--------------------- src/apps/common/event_loop.h | 5 +---- 2 files changed, 25 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/apps/common/event_loop.cpp b/src/apps/common/event_loop.cpp index bc8cf17a..b6230f4b 100644 --- a/src/apps/common/event_loop.cpp +++ b/src/apps/common/event_loop.cpp @@ -21,12 +21,35 @@ EventLoop::EventLoop() evthread_use_pthreads(); base_ = event_base_new(); instance_ = this; + + callsTrigger_ = event_new(base_, -1, EV_PERSIST, [](evutil_socket_t, short, void *closure) { + auto *self = static_cast(closure); + + for (;;) { + std::function call; + + { + std::lock_guard locker(self->lock_); + if (self->calls_.empty()) + break; + + call = std::move(self->calls_.front()); + self->calls_.pop_front(); + } + + call(); + } + }, this); + assert(callsTrigger_); + event_add(callsTrigger_, nullptr); } EventLoop::~EventLoop() { instance_ = nullptr; + event_free(callsTrigger_); + events_.clear(); event_base_free(base_); libevent_global_shutdown(); @@ -57,7 +80,7 @@ void EventLoop::callLater(std::function &&func) calls_.push_back(std::move(func)); } - event_base_once(base_, -1, EV_TIMEOUT, dispatchCallback, this, nullptr); + event_active(callsTrigger_, 0, 0); } void EventLoop::addFdEvent(int fd, EventType type, @@ -108,29 +131,6 @@ void EventLoop::addTimerEvent(const std::chrono::microseconds period, events_.push_back(std::move(event)); } -void EventLoop::dispatchCallback([[maybe_unused]] evutil_socket_t fd, - [[maybe_unused]] short flags, void *param) -{ - EventLoop *loop = static_cast(param); - loop->dispatchCall(); -} - -void EventLoop::dispatchCall() -{ - std::function call; - - { - std::unique_lock locker(lock_); - if (calls_.empty()) - return; - - call = calls_.front(); - calls_.pop_front(); - } - - call(); -} - EventLoop::Event::Event(std::function &&callback) : callback_(std::move(callback)), event_(nullptr) { diff --git a/src/apps/common/event_loop.h b/src/apps/common/event_loop.h index 76007588..53b2c37d 100644 --- a/src/apps/common/event_loop.h +++ b/src/apps/common/event_loop.h @@ -65,11 +65,8 @@ private: int exitCode_; std::deque> calls_; + struct event *callsTrigger_ = nullptr; std::list> events_; std::mutex lock_; - - static void dispatchCallback(evutil_socket_t fd, short flags, - void *param); - void dispatchCall(); }; -- cgit v1.2.1