From dbbeddecb55c7bd5ca5239f0c040886cde7e29d7 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 7 Jan 2022 17:07:31 +0200 Subject: App: Optimizing periodic events IssueID #416 --- src/app.c | 12 ++++-------- src/app.h | 1 + src/periodic.c | 25 +++++++++++++++++++++++++ src/periodic.h | 1 + 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/app.c b/src/app.c index 1a24e86c..0a17a665 100644 --- a/src/app.c +++ b/src/app.c @@ -1237,9 +1237,6 @@ iBool findCachedContent_App(const iString *url, iString *mime_out, iBlock *data_ #endif iLocalDef iBool isWaitingAllowed_App_(iApp *d) { - if (!isEmpty_Periodic(&d->periodic)) { - return iFalse; - } if (d->warmupFrames > 0) { return iFalse; } @@ -1253,10 +1250,6 @@ iLocalDef iBool isWaitingAllowed_App_(iApp *d) { static iBool nextEvent_App_(iApp *d, enum iAppEventMode eventMode, SDL_Event *event) { if (eventMode == waitForNewEvents_AppEventMode && isWaitingAllowed_App_(d)) { - /* If there are periodic commands pending, wait only for a short while. */ - if (!isEmpty_Periodic(&d->periodic)) { - return SDL_WaitEventTimeout(event, 500); - } /* We may be allowed to block here until an event comes in. */ if (isWaitingAllowed_App_(d)) { return SDL_WaitEvent(event); @@ -1348,6 +1341,10 @@ void processEvents_App(enum iAppEventMode eventMode) { break; } default: { + if (ev.type == SDL_USEREVENT && ev.user.code == periodic_UserEventCode) { + dispatchCommands_Periodic(&d->periodic); + continue; + } #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) if (ev.type == SDL_USEREVENT && ev.user.code == asleep_UserEventCode) { if (SDL_GetTicks() - d->lastEventTime > idleThreshold_App_ && @@ -1580,7 +1577,6 @@ static int run_App_(iApp *d) { SDL_AddEventWatch(resizeWatcher_, d); /* redraw window during resizing */ #endif while (d->isRunning) { - dispatchCommands_Periodic(&d->periodic); processEvents_App(waitForNewEvents_AppEventMode); runTickers_App_(d); refresh_App(); diff --git a/src/app.h b/src/app.h index d15e1f21..5968de0d 100644 --- a/src/app.h +++ b/src/app.h @@ -61,6 +61,7 @@ enum iUserEventCode { command_UserEventCode = 1, refresh_UserEventCode, asleep_UserEventCode, + periodic_UserEventCode, /* The start of a potential touch tap event is notified via a custom event because sending SDL_MOUSEBUTTONDOWN would be premature: we don't know how long the tap will take, it could turn into a tap-and-hold for example. */ diff --git a/src/periodic.c b/src/periodic.c index c65c8b07..b4f51ed3 100644 --- a/src/periodic.c +++ b/src/periodic.c @@ -57,6 +57,25 @@ iDefineTypeConstructionArgs(PeriodicCommand, (iAny *ctx, const char *cmd), ctx, static const uint32_t postingInterval_Periodic_ = 500; +static uint32_t postEvent_Periodic_(uint32_t interval, void *context) { + iUnused(context); + SDL_UserEvent ev = { .type = SDL_USEREVENT, + .timestamp = SDL_GetTicks(), + .code = periodic_UserEventCode }; + SDL_PushEvent((SDL_Event *) &ev); + return interval; +} + +static void startOrStopWakeupTimer_Periodic_(iPeriodic *d, iBool start) { + if (start && !d->wakeupTimer) { + d->wakeupTimer = SDL_AddTimer(postingInterval_Periodic_, postEvent_Periodic_, d); + } + else if (!start && d->wakeupTimer) { + SDL_RemoveTimer(d->wakeupTimer); + d->wakeupTimer = 0; + } +} + static void removePending_Periodic_(iPeriodic *d) { iForEach(PtrSet, i, &d->pendingRemoval) { size_t pos; @@ -68,6 +87,9 @@ static void removePending_Periodic_(iPeriodic *d) { } } clear_PtrSet(&d->pendingRemoval); + if (isEmpty_SortedArray(&d->commands)) { + startOrStopWakeupTimer_Periodic_(d, iFalse); + } } static iBool isDispatching_; @@ -109,9 +131,11 @@ void init_Periodic(iPeriodic *d) { init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_); d->lastPostTime = 0; init_PtrSet(&d->pendingRemoval); + d->wakeupTimer = 0; } void deinit_Periodic(iPeriodic *d) { + startOrStopWakeupTimer_Periodic_(d, iFalse); deinit_PtrSet(&d->pendingRemoval); iForEach(Array, i, &d->commands.values) { deinit_PeriodicCommand(i.value); @@ -134,6 +158,7 @@ void add_Periodic(iPeriodic *d, iAny *context, const char *command) { init_PeriodicCommand(&pc, context, command); insert_SortedArray(&d->commands, &pc); } + startOrStopWakeupTimer_Periodic_(d, iTrue); unlock_Mutex(d->mutex); } diff --git a/src/periodic.h b/src/periodic.h index a56310a8..f65a4299 100644 --- a/src/periodic.h +++ b/src/periodic.h @@ -35,6 +35,7 @@ struct Impl_Periodic { iSortedArray commands; uint32_t lastPostTime; iPtrSet pendingRemoval; /* contexts */ + int wakeupTimer; /* running while there are pending periodic commands */ }; void init_Periodic (iPeriodic *); -- cgit v1.2.3