diff --git a/filter/filter.c b/filter/filter.c index 4eaf6405..43cb5887 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -55,12 +55,12 @@ void (*bt_assert_hook)(int result, struct f_inst *assert); struct filter_roa_reloader { node n; - struct listener *L; + LISTENER(rt_notify_data) *L; struct rtable *roa_table; struct filter_slot *slot; }; -static void filter_roa_reloader_notify(void *self, const void *data UNUSED) { +static void filter_roa_reloader_notify(void *self, const rt_notify_data *data UNUSED) { struct filter_roa_reloader *frr = self; frr->slot->reloader(frr->slot); } @@ -82,7 +82,7 @@ static void filter_roa_reloader_subscribe(struct rtable *roa_table, struct filte frr->roa_table = roa_table; frr->slot = slot; add_tail(&(slot->notifiers), &(frr->n)); - frr->L = subscribe(slot->p, &(roa_table->listeners), filter_roa_reloader_notify, filter_roa_reloader_unsubscribe, frr); + frr->L = SUBSCRIBE(rt_notify_data, slot->p, roa_table->listeners, frr, filter_roa_reloader_notify, filter_roa_reloader_unsubscribe); } static struct adata undef_adata; /* adata of length 0 used for undefined */ diff --git a/nest/notify.c b/nest/notify.c index fac1ac81..874263e0 100644 --- a/nest/notify.c +++ b/nest/notify.c @@ -10,63 +10,21 @@ #include "lib/resource.h" #include "nest/notify.h" -struct listener { - resource r; - node n; - - void (*notify)(void *self, const void *data); - void (*unsubscribe)(void *self); - - void *self; -}; +LISTENER_DECL(void); static void listener_unsubscribe(resource *r) { - struct listener *L = (struct listener *) r; + LISTENER(void) *L = (LISTENER(void) *) r; rem_node(&(L->n)); CALL(L->unsubscribe, L->self); } -static struct resclass listener_class = { +struct resclass listener_class = { .name = "Listener", - .size = sizeof(struct listener), + .size = sizeof(LISTENER(void)), .free = listener_unsubscribe, .dump = NULL, .lookup = NULL, .memsize = NULL, }; - -struct listener * -subscribe(pool *p, list *sender, void (*notify)(void *, const void *), void (*unsubscribe)(void *), void *self) -{ - struct listener *L = ralloc(p, &listener_class); - L->notify = notify; - L->unsubscribe = unsubscribe; - L->self = self; - - add_tail(sender, &(L->n)); - return L; -} - -void unsubscribe(struct listener *L) -{ - L->unsubscribe = NULL; - rfree(L); -} - -void unsubscribe_all(list *sender) -{ - struct listener *L; - node *x, *y; - WALK_LIST2_DELSAFE(L, x, y, *sender, n) - rfree(L); -} - -void notify(list *sender, const void *data) -{ - struct listener *L; - node *x, *y; - WALK_LIST2_DELSAFE(L, x, y, *sender, n) - L->notify(L->self, data); -} diff --git a/nest/notify.h b/nest/notify.h index 22b67cc5..6fd47fed 100644 --- a/nest/notify.h +++ b/nest/notify.h @@ -12,11 +12,45 @@ #include "lib/resource.h" #include "lib/lists.h" -struct listener; +#define LISTENER(stype) struct listener__##stype +#define LISTENER_DECL(stype) LISTENER(stype) { \ + resource r; \ + node n; \ + void *self; \ + void (*unsubscribe)(void *self); \ + void (*notify)(void *self, const stype *data); \ +}; -struct listener *subscribe(pool *p, list *sender, void (*notify)(void *self, const void *data), void (*unsubscribe)(void *self), void *self); -void unsubscribe(struct listener *L); -void unsubscribe_all(list *sender); -void notify(list *sender, const void *data); +extern struct resclass listener_class; + +#define SUBSCRIBE(stype, pool, sender, _self, _notify, _unsubscribe) ({ \ + LISTENER(stype) *L = ralloc(pool, &listener_class); \ + L->notify = _notify; \ + L->unsubscribe = _unsubscribe; \ + L->self = _self; \ + add_tail(&(sender), &(L->n)); \ + L; \ + }) + +#define UNSUBSCRIBE(stype, listener) do { \ + LISTENER(stype) *L = listener; \ + L->unsubscribe = NULL; \ + rfree(L); \ +} while (0) + +#define UNNOTIFY(stype, sender) do { \ + LISTENER(stype) *L; \ + node *x, *y; \ + WALK_LIST2_DELSAFE(L, x, y, sender, n) \ + rfree(L); \ +} while (0) + +#define NOTIFY(stype, sender, data) do { \ + const stype *_d = data; \ + LISTENER(stype) *L; \ + node *x, *y; \ + WALK_LIST2_DELSAFE(L, x, y, sender, n) \ + L->notify(L->self, _d); \ +} while (0) #endif diff --git a/nest/route.h b/nest/route.h index 00747b6c..9a946d2d 100644 --- a/nest/route.h +++ b/nest/route.h @@ -13,6 +13,8 @@ #include "lib/resource.h" #include "lib/net.h" +#include "nest/notify.h" + struct ea_list; struct protocol; struct proto; @@ -320,10 +322,12 @@ void rt_reload_channel_abort(struct channel *c); void rt_prune_sync(rtable *t, int all); struct rtable_config *rt_new_table(struct symbol *s, uint addr_type); -struct rt_notify { +typedef struct rt_notify { struct network *net; rte *new, *old, *new_best, *old_best, *before_old; -}; +} rt_notify_data; + +LISTENER_DECL(rt_notify_data); /* Default limit for ECMP next hops, defined in sysdep code */ extern const int rt_default_ecmp; diff --git a/nest/rt-table.c b/nest/rt-table.c index 0646ece3..6817df2d 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -951,7 +951,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, .before_old = before_old, }; - notify(&(tab->listeners), &rtn); + NOTIFY(rt_notify_data, tab->listeners, &rtn); } static inline int @@ -2173,6 +2173,7 @@ rt_unlock_table(rtable *r) r->config->table = NULL; if (r->hostcache) rt_free_hostcache(r); + UNNOTIFY(rt_notify_data, r->listeners); rem_node(&r->n); fib_free(&r->fib); rfree(r->rt_event);