Skip to content
This repository was archived by the owner on Aug 19, 2021. It is now read-only.

Commit 02ce85d

Browse files
committed
Restructured dispatch to calculate wait after dispatching callbacks
Event callbacks may take a non-trivial amount of time. This can cause a pre-calculated wait to become inaccurate. Calculating the wait after possibly requeueing events also removes the need for the redundant semaphore for periodic events.
1 parent 52e0aa2 commit 02ce85d

File tree

1 file changed

+19
-22
lines changed

1 file changed

+19
-22
lines changed

equeue.c

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -204,18 +204,12 @@ static void equeue_unqueue(equeue_t *q, struct equeue_event *e) {
204204
}
205205
}
206206

207-
static struct equeue_event *equeue_dequeue(equeue_t *q, int *deadline) {
207+
static struct equeue_event *equeue_dequeue(equeue_t *q) {
208208
unsigned target = equeue_tick();
209209
struct equeue_event *head = 0;
210210
struct equeue_event **tail = &head;
211211

212-
while (q->queue) {
213-
int diff = equeue_tickdiff(q->queue->target, target);
214-
if (diff > 0) {
215-
*deadline = diff;
216-
break;
217-
}
218-
212+
while (q->queue && equeue_tickdiff(q->queue->target, target) <= 0) {
219213
struct equeue_event *es = q->queue;
220214
q->queue = es->next;
221215

@@ -296,18 +290,14 @@ void equeue_dispatch(equeue_t *q, int ms) {
296290

297291
while (1) {
298292
// collect all the available events and next deadline
299-
struct equeue_event *es = 0;
300-
int deadline = -1;
301-
if (q->queue) {
302-
equeue_mutex_lock(&q->queuelock);
303-
es = equeue_dequeue(q, &deadline);
293+
equeue_mutex_lock(&q->queuelock);
294+
struct equeue_event *es = equeue_dequeue(q);
304295

305-
// mark events as in-flight
306-
for (struct equeue_event *e = es; e; e = e->next) {
307-
e->id = -e->id;
308-
}
309-
equeue_mutex_unlock(&q->queuelock);
296+
// mark events as in-flight
297+
for (struct equeue_event *e = es; e; e = e->next) {
298+
e->id = -e->id;
310299
}
300+
equeue_mutex_unlock(&q->queuelock);
311301

312302
// dispatch events
313303
while (es) {
@@ -326,25 +316,32 @@ void equeue_dispatch(equeue_t *q, int ms) {
326316
e->id = -e->id;
327317
equeue_enqueue(q, e, e->period);
328318
equeue_mutex_unlock(&q->queuelock);
329-
330-
equeue_sema_signal(&q->eventsema);
331319
} else {
332320
e->id = equeue_incid(q, -e->id);
333321
equeue_dealloc(q, e+1);
334322
}
335323
}
336324

325+
int deadline = -1;
326+
unsigned tick = equeue_tick();
327+
337328
// check if we should stop dispatching soon
338329
if (ms >= 0) {
339-
int diff = equeue_tickdiff(timeout, equeue_tick());
340-
if (diff <= 0) {
330+
deadline = equeue_tickdiff(timeout, tick);
331+
if (deadline <= 0) {
341332
return;
342333
}
334+
}
343335

336+
// find closest deadline
337+
equeue_mutex_lock(&q->queuelock);
338+
if (q->queue) {
339+
int diff = equeue_tickdiff(q->queue->target, tick);
344340
if (deadline < 0 || diff < deadline) {
345341
deadline = diff;
346342
}
347343
}
344+
equeue_mutex_unlock(&q->queuelock);
348345

349346
// wait for events
350347
equeue_sema_wait(&q->eventsema, deadline);

0 commit comments

Comments
 (0)