event/DeferEvent: add ScheduleNext()

This commit is contained in:
Max Kellermann 2025-01-13 14:05:57 +01:00 committed by Max Kellermann
parent 4bb379a218
commit 5e107c33d9
4 changed files with 40 additions and 1 deletions

@ -21,3 +21,12 @@ DeferEvent::ScheduleIdle() noexcept
assert(IsPending());
}
void
DeferEvent::ScheduleNext() noexcept
{
if (!IsPending())
loop.AddNext(*this);
assert(IsPending());
}

@ -49,6 +49,15 @@ public:
*/
void ScheduleIdle() noexcept;
/**
* Schedule this event, but only after the next #EventLoop
* iteration (i.e. after the epoll_wait() call, after handling
* all pending I/O events). This is useful for repeated I/O
* operations that should not occupy the whole #EventLoop,
* starving all other I/O events.
*/
void ScheduleNext() noexcept;
void Cancel() noexcept {
if (IsPending())
unlink();

@ -45,6 +45,7 @@ EventLoop::~EventLoop() noexcept
assert(defer.empty());
assert(idle.empty());
assert(next.empty());
#ifdef HAVE_THREADED_EVENT_LOOP
assert(inject.empty());
#endif
@ -201,6 +202,14 @@ EventLoop::AddIdle(DeferEvent &e) noexcept
#endif
}
void
EventLoop::AddNext(DeferEvent &e) noexcept
{
assert(IsInside());
next.push_back(e);
}
void
EventLoop::RunDeferred() noexcept
{
@ -295,7 +304,7 @@ EventLoop::Run() noexcept
/* invoke timers */
const auto timeout = HandleTimers();
Event::Duration timeout = HandleTimers();
if (quit)
break;
@ -331,8 +340,13 @@ EventLoop::Run() noexcept
/* wait for new event */
if (!next.empty())
timeout = Event::Duration{0};
Wait(timeout);
idle.splice(std::next(idle.begin()), next);
FlushClockCaches();
#ifdef HAVE_THREADED_EVENT_LOOP

@ -67,6 +67,12 @@ class EventLoop final
*/
DeferList idle;
/**
* This is like #idle, but gets invoked after the next
* epoll_wait() call.
*/
DeferList next;
#ifdef HAVE_THREADED_EVENT_LOOP
Mutex mutex;
@ -226,6 +232,7 @@ public:
*/
void AddDefer(DeferEvent &e) noexcept;
void AddIdle(DeferEvent &e) noexcept;
void AddNext(DeferEvent &e) noexcept;
#ifdef HAVE_THREADED_EVENT_LOOP
/**