summaryrefslogtreecommitdiff
path: root/src/periodic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/periodic.c')
-rw-r--r--src/periodic.c32
1 files changed, 25 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}