diff options
author | Maria Matejka <mq@ucw.cz> | 2021-10-20 23:08:58 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2021-11-22 19:05:43 +0100 |
commit | 6e841b3153565632b6753f6b1fe74850c37f2808 (patch) | |
tree | 2673e3718fec066c90a000c0ad216f62a4de3755 /lib/event.c | |
parent | 94eb0858c2b938549d9d1703c872c6149901e7dd (diff) |
Adding a generic cork mechanism for events
Diffstat (limited to 'lib/event.c')
-rw-r--r-- | lib/event.c | 74 |
1 files changed, 68 insertions, 6 deletions
diff --git a/lib/event.c b/lib/event.c index 6c5c8b14..5031f314 100644 --- a/lib/event.c +++ b/lib/event.c @@ -114,17 +114,42 @@ ev_send(event_list *l, event *e) e->list = l; - LOCK_DOMAIN(event, l->lock); - if (enlisted(&e->n)) + struct event_cork *ec = e->cork; + + uint ping = 0; + + if (ec) { + LOCK_DOMAIN(cork, ec->lock); + LOCK_DOMAIN(event, l->lock); + + if (!enlisted(&e->n)) + if (ec->count) + add_tail(&ec->events, &e->n); + else + { + add_tail(&l->events, &e->n); + ping = 1; + } + UNLOCK_DOMAIN(event, l->lock); - return; + UNLOCK_DOMAIN(cork, ec->lock); } + else + { + LOCK_DOMAIN(event, l->lock); - add_tail(&l->events, &e->n); - UNLOCK_DOMAIN(event, l->lock); + if (!enlisted(&e->n)) + { + add_tail(&l->events, &e->n); + ping = 1; + } - birdloop_ping(l->loop); + UNLOCK_DOMAIN(event, l->lock); + } + + if (ping) + birdloop_ping(l->loop); } void io_log_event(void *hook, void *data); @@ -224,3 +249,40 @@ ev_run_list_limited(event_list *l, uint limit) return repeat; } + +void ev_cork(struct event_cork *ec) +{ + LOCK_DOMAIN(cork, ec->lock); + ec->count++; + UNLOCK_DOMAIN(cork, ec->lock); +} + +void ev_uncork(struct event_cork *ec) +{ + LOCK_DOMAIN(cork, ec->lock); + + if (--ec->count) + { + UNLOCK_DOMAIN(cork, ec->lock); + return; + } + + node *n; + WALK_LIST_FIRST(n, ec->events) + { + event *e = SKIP_BACK(event, n, n); + event_list *el = e->list; + + rem_node(&e->n); + + LOCK_DOMAIN(event, el->lock); + add_tail(&el->events, &e->n); + UNLOCK_DOMAIN(event, el->lock); + + birdloop_ping(el->loop); + } + + UNLOCK_DOMAIN(cork, ec->lock); + + birdloop_ping(&main_birdloop); +} |