apps: common: event_loop: Use single event source for deferred calls
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 <pobrn@protonmail.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
This commit is contained in:
parent
54055dd0c2
commit
234eb60546
2 changed files with 25 additions and 28 deletions
|
@ -21,12 +21,35 @@ EventLoop::EventLoop()
|
||||||
evthread_use_pthreads();
|
evthread_use_pthreads();
|
||||||
base_ = event_base_new();
|
base_ = event_base_new();
|
||||||
instance_ = this;
|
instance_ = this;
|
||||||
|
|
||||||
|
callsTrigger_ = event_new(base_, -1, EV_PERSIST, [](evutil_socket_t, short, void *closure) {
|
||||||
|
auto *self = static_cast<EventLoop *>(closure);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
std::function<void()> 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()
|
EventLoop::~EventLoop()
|
||||||
{
|
{
|
||||||
instance_ = nullptr;
|
instance_ = nullptr;
|
||||||
|
|
||||||
|
event_free(callsTrigger_);
|
||||||
|
|
||||||
events_.clear();
|
events_.clear();
|
||||||
event_base_free(base_);
|
event_base_free(base_);
|
||||||
libevent_global_shutdown();
|
libevent_global_shutdown();
|
||||||
|
@ -57,7 +80,7 @@ void EventLoop::callLater(std::function<void()> &&func)
|
||||||
calls_.push_back(std::move(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,
|
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));
|
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<EventLoop *>(param);
|
|
||||||
loop->dispatchCall();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventLoop::dispatchCall()
|
|
||||||
{
|
|
||||||
std::function<void()> call;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> locker(lock_);
|
|
||||||
if (calls_.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
call = calls_.front();
|
|
||||||
calls_.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
call();
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLoop::Event::Event(std::function<void()> &&callback)
|
EventLoop::Event::Event(std::function<void()> &&callback)
|
||||||
: callback_(std::move(callback)), event_(nullptr)
|
: callback_(std::move(callback)), event_(nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,11 +65,8 @@ private:
|
||||||
int exitCode_;
|
int exitCode_;
|
||||||
|
|
||||||
std::deque<std::function<void()>> calls_;
|
std::deque<std::function<void()>> calls_;
|
||||||
|
struct event *callsTrigger_ = nullptr;
|
||||||
|
|
||||||
std::list<std::unique_ptr<Event>> events_;
|
std::list<std::unique_ptr<Event>> events_;
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
|
|
||||||
static void dispatchCallback(evutil_socket_t fd, short flags,
|
|
||||||
void *param);
|
|
||||||
void dispatchCall();
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue