diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-07 17:07:31 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-07 17:07:31 +0200 |
commit | dbbeddecb55c7bd5ca5239f0c040886cde7e29d7 (patch) | |
tree | c0e0103322c6e97609695b1ed569bf664f6a0bdd | |
parent | 9d5a4c29efe45644d379eaaa020058beb4dd96f6 (diff) |
App: Optimizing periodic events
IssueID #416
-rw-r--r-- | src/app.c | 12 | ||||
-rw-r--r-- | src/app.h | 1 | ||||
-rw-r--r-- | src/periodic.c | 25 | ||||
-rw-r--r-- | src/periodic.h | 1 |
4 files changed, 31 insertions, 8 deletions
@@ -1237,9 +1237,6 @@ iBool findCachedContent_App(const iString *url, iString *mime_out, iBlock *data_ | |||
1237 | #endif | 1237 | #endif |
1238 | 1238 | ||
1239 | iLocalDef iBool isWaitingAllowed_App_(iApp *d) { | 1239 | iLocalDef iBool isWaitingAllowed_App_(iApp *d) { |
1240 | if (!isEmpty_Periodic(&d->periodic)) { | ||
1241 | return iFalse; | ||
1242 | } | ||
1243 | if (d->warmupFrames > 0) { | 1240 | if (d->warmupFrames > 0) { |
1244 | return iFalse; | 1241 | return iFalse; |
1245 | } | 1242 | } |
@@ -1253,10 +1250,6 @@ iLocalDef iBool isWaitingAllowed_App_(iApp *d) { | |||
1253 | 1250 | ||
1254 | static iBool nextEvent_App_(iApp *d, enum iAppEventMode eventMode, SDL_Event *event) { | 1251 | static iBool nextEvent_App_(iApp *d, enum iAppEventMode eventMode, SDL_Event *event) { |
1255 | if (eventMode == waitForNewEvents_AppEventMode && isWaitingAllowed_App_(d)) { | 1252 | if (eventMode == waitForNewEvents_AppEventMode && isWaitingAllowed_App_(d)) { |
1256 | /* If there are periodic commands pending, wait only for a short while. */ | ||
1257 | if (!isEmpty_Periodic(&d->periodic)) { | ||
1258 | return SDL_WaitEventTimeout(event, 500); | ||
1259 | } | ||
1260 | /* We may be allowed to block here until an event comes in. */ | 1253 | /* We may be allowed to block here until an event comes in. */ |
1261 | if (isWaitingAllowed_App_(d)) { | 1254 | if (isWaitingAllowed_App_(d)) { |
1262 | return SDL_WaitEvent(event); | 1255 | return SDL_WaitEvent(event); |
@@ -1348,6 +1341,10 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1348 | break; | 1341 | break; |
1349 | } | 1342 | } |
1350 | default: { | 1343 | default: { |
1344 | if (ev.type == SDL_USEREVENT && ev.user.code == periodic_UserEventCode) { | ||
1345 | dispatchCommands_Periodic(&d->periodic); | ||
1346 | continue; | ||
1347 | } | ||
1351 | #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) | 1348 | #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) |
1352 | if (ev.type == SDL_USEREVENT && ev.user.code == asleep_UserEventCode) { | 1349 | if (ev.type == SDL_USEREVENT && ev.user.code == asleep_UserEventCode) { |
1353 | if (SDL_GetTicks() - d->lastEventTime > idleThreshold_App_ && | 1350 | if (SDL_GetTicks() - d->lastEventTime > idleThreshold_App_ && |
@@ -1580,7 +1577,6 @@ static int run_App_(iApp *d) { | |||
1580 | SDL_AddEventWatch(resizeWatcher_, d); /* redraw window during resizing */ | 1577 | SDL_AddEventWatch(resizeWatcher_, d); /* redraw window during resizing */ |
1581 | #endif | 1578 | #endif |
1582 | while (d->isRunning) { | 1579 | while (d->isRunning) { |
1583 | dispatchCommands_Periodic(&d->periodic); | ||
1584 | processEvents_App(waitForNewEvents_AppEventMode); | 1580 | processEvents_App(waitForNewEvents_AppEventMode); |
1585 | runTickers_App_(d); | 1581 | runTickers_App_(d); |
1586 | refresh_App(); | 1582 | refresh_App(); |
@@ -61,6 +61,7 @@ enum iUserEventCode { | |||
61 | command_UserEventCode = 1, | 61 | command_UserEventCode = 1, |
62 | refresh_UserEventCode, | 62 | refresh_UserEventCode, |
63 | asleep_UserEventCode, | 63 | asleep_UserEventCode, |
64 | periodic_UserEventCode, | ||
64 | /* The start of a potential touch tap event is notified via a custom event because | 65 | /* The start of a potential touch tap event is notified via a custom event because |
65 | sending SDL_MOUSEBUTTONDOWN would be premature: we don't know how long the tap will | 66 | sending SDL_MOUSEBUTTONDOWN would be premature: we don't know how long the tap will |
66 | take, it could turn into a tap-and-hold for example. */ | 67 | 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, | |||
57 | 57 | ||
58 | static const uint32_t postingInterval_Periodic_ = 500; | 58 | static const uint32_t postingInterval_Periodic_ = 500; |
59 | 59 | ||
60 | static uint32_t postEvent_Periodic_(uint32_t interval, void *context) { | ||
61 | iUnused(context); | ||
62 | SDL_UserEvent ev = { .type = SDL_USEREVENT, | ||
63 | .timestamp = SDL_GetTicks(), | ||
64 | .code = periodic_UserEventCode }; | ||
65 | SDL_PushEvent((SDL_Event *) &ev); | ||
66 | return interval; | ||
67 | } | ||
68 | |||
69 | static void startOrStopWakeupTimer_Periodic_(iPeriodic *d, iBool start) { | ||
70 | if (start && !d->wakeupTimer) { | ||
71 | d->wakeupTimer = SDL_AddTimer(postingInterval_Periodic_, postEvent_Periodic_, d); | ||
72 | } | ||
73 | else if (!start && d->wakeupTimer) { | ||
74 | SDL_RemoveTimer(d->wakeupTimer); | ||
75 | d->wakeupTimer = 0; | ||
76 | } | ||
77 | } | ||
78 | |||
60 | static void removePending_Periodic_(iPeriodic *d) { | 79 | static void removePending_Periodic_(iPeriodic *d) { |
61 | iForEach(PtrSet, i, &d->pendingRemoval) { | 80 | iForEach(PtrSet, i, &d->pendingRemoval) { |
62 | size_t pos; | 81 | size_t pos; |
@@ -68,6 +87,9 @@ static void removePending_Periodic_(iPeriodic *d) { | |||
68 | } | 87 | } |
69 | } | 88 | } |
70 | clear_PtrSet(&d->pendingRemoval); | 89 | clear_PtrSet(&d->pendingRemoval); |
90 | if (isEmpty_SortedArray(&d->commands)) { | ||
91 | startOrStopWakeupTimer_Periodic_(d, iFalse); | ||
92 | } | ||
71 | } | 93 | } |
72 | 94 | ||
73 | static iBool isDispatching_; | 95 | static iBool isDispatching_; |
@@ -109,9 +131,11 @@ void init_Periodic(iPeriodic *d) { | |||
109 | init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_); | 131 | init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_); |
110 | d->lastPostTime = 0; | 132 | d->lastPostTime = 0; |
111 | init_PtrSet(&d->pendingRemoval); | 133 | init_PtrSet(&d->pendingRemoval); |
134 | d->wakeupTimer = 0; | ||
112 | } | 135 | } |
113 | 136 | ||
114 | void deinit_Periodic(iPeriodic *d) { | 137 | void deinit_Periodic(iPeriodic *d) { |
138 | startOrStopWakeupTimer_Periodic_(d, iFalse); | ||
115 | deinit_PtrSet(&d->pendingRemoval); | 139 | deinit_PtrSet(&d->pendingRemoval); |
116 | iForEach(Array, i, &d->commands.values) { | 140 | iForEach(Array, i, &d->commands.values) { |
117 | deinit_PeriodicCommand(i.value); | 141 | deinit_PeriodicCommand(i.value); |
@@ -134,6 +158,7 @@ void add_Periodic(iPeriodic *d, iAny *context, const char *command) { | |||
134 | init_PeriodicCommand(&pc, context, command); | 158 | init_PeriodicCommand(&pc, context, command); |
135 | insert_SortedArray(&d->commands, &pc); | 159 | insert_SortedArray(&d->commands, &pc); |
136 | } | 160 | } |
161 | startOrStopWakeupTimer_Periodic_(d, iTrue); | ||
137 | unlock_Mutex(d->mutex); | 162 | unlock_Mutex(d->mutex); |
138 | } | 163 | } |
139 | 164 | ||
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 { | |||
35 | iSortedArray commands; | 35 | iSortedArray commands; |
36 | uint32_t lastPostTime; | 36 | uint32_t lastPostTime; |
37 | iPtrSet pendingRemoval; /* contexts */ | 37 | iPtrSet pendingRemoval; /* contexts */ |
38 | int wakeupTimer; /* running while there are pending periodic commands */ | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | void init_Periodic (iPeriodic *); | 41 | void init_Periodic (iPeriodic *); |