diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-29 16:53:12 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-29 16:53:12 +0300 |
commit | d4788f5eb3f94e01a6575f227f2ab80330f1a8e1 (patch) | |
tree | 09c028105b4e34a2969e32e2c49405d48a6b9f01 | |
parent | de2dd81306da54b0bfdd9b075dc5de90c871b9af (diff) |
Periodic: Handling removal during iteration
-rw-r--r-- | src/periodic.c | 32 | ||||
-rw-r--r-- | src/periodic.h | 2 |
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 | ||
58 | static const uint32_t postingInterval_Periodic_ = 500; | 58 | static const uint32_t postingInterval_Periodic_ = 500; |
59 | 59 | ||
60 | static 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 | |||
73 | static iBool isDispatching_; | ||
74 | |||
60 | iBool dispatchCommands_Periodic(iPeriodic *d) { | 75 | iBool 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 | ||
92 | void deinit_Periodic(iPeriodic *d) { | 112 | void 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 | ||
116 | void remove_Periodic(iPeriodic *d, iAny *context) { | 137 | void 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 | |||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 21 | SOFTWARE, 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 | ||
26 | iDeclareType(Periodic) | 27 | iDeclareType(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 | ||
36 | void init_Periodic (iPeriodic *); | 38 | void init_Periodic (iPeriodic *); |