diff options
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); +} |