summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-04-29 16:53:12 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-04-29 16:53:12 +0300
commitd4788f5eb3f94e01a6575f227f2ab80330f1a8e1 (patch)
tree09c028105b4e34a2969e32e2c49405d48a6b9f01
parentde2dd81306da54b0bfdd9b075dc5de90c871b9af (diff)
Periodic: Handling removal during iteration
-rw-r--r--src/periodic.c32
-rw-r--r--src/periodic.h2
2 files changed, 27 insertions, 7 deletions
diff --git a/src/periodic.c b/src/periodic.c
index 0291ff98..068f2a1e 100644
--- a/src/periodic.c
+++ b/src/periodic.c
@@ -57,6 +57,21 @@ iDefineTypeConstructionArgs(PeriodicCommand, (iAny *ctx, const char *cmd), ctx,
57 57
58static const uint32_t postingInterval_Periodic_ = 500; 58static const uint32_t postingInterval_Periodic_ = 500;
59 59
60static void removePending_Periodic_(iPeriodic *d) {
61 iForEach(PtrSet, i, &d->pendingRemoval) {
62 size_t pos;
63 iPeriodicCommand key = { .context = *i.value };
64 if (locate_SortedArray(&d->commands, &key, &pos)) {
65 iPeriodicCommand *pc = at_SortedArray(&d->commands, pos);
66 deinit_PeriodicCommand(pc);
67 remove_Array(&d->commands.values, pos);
68 }
69 }
70 clear_PtrSet(&d->pendingRemoval);
71}
72
73static iBool isDispatching_;
74
60iBool dispatchCommands_Periodic(iPeriodic *d) { 75iBool dispatchCommands_Periodic(iPeriodic *d) {
61 const uint32_t now = SDL_GetTicks(); 76 const uint32_t now = SDL_GetTicks();
62 if (now - d->lastPostTime < postingInterval_Periodic_) { 77 if (now - d->lastPostTime < postingInterval_Periodic_) {
@@ -65,20 +80,24 @@ iBool dispatchCommands_Periodic(iPeriodic *d) {
65 d->lastPostTime = now; 80 d->lastPostTime = now;
66 iBool wasPosted = iFalse; 81 iBool wasPosted = iFalse;
67 lock_Mutex(d->mutex); 82 lock_Mutex(d->mutex);
83 isDispatching_ = iTrue;
84 iAssert(isEmpty_PtrSet(&d->pendingRemoval));
68 iConstForEach(Array, i, &d->commands.values) { 85 iConstForEach(Array, i, &d->commands.values) {
69 const iPeriodicCommand *pc = i.value; 86 const iPeriodicCommand *pc = i.value;
87 iAssert(isInstance_Object(pc->context, &Class_Widget));
70 const SDL_UserEvent ev = { 88 const SDL_UserEvent ev = {
71 .type = SDL_USEREVENT, 89 .type = SDL_USEREVENT,
72 .code = command_UserEventCode, 90 .code = command_UserEventCode,
73 .data1 = (void *) cstr_String(&pc->command), 91 .data1 = (void *) cstr_String(&pc->command),
74 .data2 = findRoot_Window(get_Window(), pc->context) 92 .data2 = findRoot_Window(get_Window(), pc->context)
75 }; 93 };
76 iAssert(isInstance_Object(pc->context, &Class_Widget));
77 setCurrent_Root(ev.data2); 94 setCurrent_Root(ev.data2);
78 dispatchEvent_Widget(pc->context, (const SDL_Event *) &ev); 95 dispatchEvent_Widget(pc->context, (const SDL_Event *) &ev);
79 wasPosted = iTrue; 96 wasPosted = iTrue;
80 } 97 }
98 removePending_Periodic_(d);
81 setCurrent_Root(NULL); 99 setCurrent_Root(NULL);
100 isDispatching_ = iFalse;
82 unlock_Mutex(d->mutex); 101 unlock_Mutex(d->mutex);
83 return wasPosted; 102 return wasPosted;
84} 103}
@@ -87,9 +106,11 @@ void init_Periodic(iPeriodic *d) {
87 d->mutex = new_Mutex(); 106 d->mutex = new_Mutex();
88 init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_); 107 init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_);
89 d->lastPostTime = 0; 108 d->lastPostTime = 0;
109 init_PtrSet(&d->pendingRemoval);
90} 110}
91 111
92void deinit_Periodic(iPeriodic *d) { 112void deinit_Periodic(iPeriodic *d) {
113 deinit_PtrSet(&d->pendingRemoval);
93 iForEach(Array, i, &d->commands.values) { 114 iForEach(Array, i, &d->commands.values) {
94 deinit_PeriodicCommand(i.value); 115 deinit_PeriodicCommand(i.value);
95 } 116 }
@@ -115,12 +136,9 @@ void add_Periodic(iPeriodic *d, iAny *context, const char *command) {
115 136
116void remove_Periodic(iPeriodic *d, iAny *context) { 137void remove_Periodic(iPeriodic *d, iAny *context) {
117 lock_Mutex(d->mutex); 138 lock_Mutex(d->mutex);
118 size_t pos; 139 insert_PtrSet(&d->pendingRemoval, context);
119 iPeriodicCommand key = { .context = context }; 140 if (!isDispatching_) {
120 if (locate_SortedArray(&d->commands, &key, &pos)) { 141 removePending_Periodic_(d);
121 iPeriodicCommand *pc = at_SortedArray(&d->commands, pos);
122 deinit_PeriodicCommand(pc);
123 remove_Array(&d->commands.values, pos);
124 } 142 }
125 unlock_Mutex(d->mutex); 143 unlock_Mutex(d->mutex);
126} 144}
diff --git a/src/periodic.h b/src/periodic.h
index 8886617b..3a0501d9 100644
--- a/src/periodic.h
+++ b/src/periodic.h
@@ -21,6 +21,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22 22
23#include <the_Foundation/mutex.h> 23#include <the_Foundation/mutex.h>
24#include <the_Foundation/ptrset.h>
24#include <the_Foundation/sortedarray.h> 25#include <the_Foundation/sortedarray.h>
25 26
26iDeclareType(Periodic) 27iDeclareType(Periodic)
@@ -31,6 +32,7 @@ struct Impl_Periodic {
31 iMutex * mutex; 32 iMutex * mutex;
32 iSortedArray commands; 33 iSortedArray commands;
33 uint32_t lastPostTime; 34 uint32_t lastPostTime;
35 iPtrSet pendingRemoval; /* contexts */
34}; 36};
35 37
36void init_Periodic (iPeriodic *); 38void init_Periodic (iPeriodic *);