From: Maria Matejka Date: Mon, 11 Mar 2019 22:23:21 +0000 (+0100) Subject: Notify: Also the listener list is typed. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9d27e7c98bfa165f0c0e1d9a07c3d2353359e0e6;p=thirdparty%2Fbird.git Notify: Also the listener list is typed. --- diff --git a/lib/tlists.h b/lib/tlists.h new file mode 100644 index 000000000..e066928d0 --- /dev/null +++ b/lib/tlists.h @@ -0,0 +1,61 @@ +/* + * BIRD Library -- Typed Linked Lists + * + * (c) 2019 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + * + * Based roughly on Martin Mares' lib/lists.h but completely implemented as macros. + */ + +#ifndef _BIRD_TLISTS_H_ +#define _BIRD_TLISTS_H_ + +#define TNODE(t) struct tnode__##t +#define TNODE_DEF(t) +#define TLIST(t) union tlist__##t +#define TLIST_DEF(t) TNODE(t) { \ + TNODE(t) *next; \ + struct t *self; \ + TNODE(t) *prev; \ +}; \ + TLIST(t) { \ + struct { \ + TNODE(t) head_node; \ + struct t *head_null_self; \ + TNODE(t) *tail; \ + }; \ + struct { \ + TNODE(t) *head; \ + struct t *tail_padding_self; \ + TNODE(t) tail_node; \ + }; \ +} + +#define INIT_TLIST(t, list) do { \ + memset(&(list), 0, sizeof(TLIST(t))); \ + list.head_node.next = &(list.tail_node); \ + list.tail_node.prev = &(list.head_node); \ +} while (0) + +#define TNODE_VALID(t, n) ((n)->next) +#define WALK_TLIST(t, n, list) for (TNODE(t) *n = list.head; TNODE_VALID(t, n); n = n->next) +#define WALK_TLIST_DELSAFE(t, n, list) \ + for (TNODE(t) *n = list.head, *_n; _n = n->next; n = _n) + +#define TADD_TAIL(t, list, node) do { \ + TNODE(t) *p = list.tail; \ + node.prev = p; \ + node.next = &(list.tail_node); \ + p->next = &(node); \ + list.tail = &(node); \ +} while (0) + +#define TREM_NODE(t, node) do { \ + TNODE(t) *p = node.prev, *n = node.next; \ + node.prev = node.next = NULL; \ + p->next = n; \ + n->prev = p; \ +} while (0) + +#endif diff --git a/nest/Makefile b/nest/Makefile index dae45b029..884d39506 100644 --- a/nest/Makefile +++ b/nest/Makefile @@ -1,4 +1,4 @@ -src := a-path.c a-set.c cli.c cmds.c iface.c locks.c neighbor.c notify.c password.c proto.c rt-attr.c rt-dev.c rt-fib.c rt-show.c rt-table.c +src := a-path.c a-set.c cli.c cmds.c iface.c locks.c neighbor.c password.c proto.c rt-attr.c rt-dev.c rt-fib.c rt-show.c rt-table.c obj := $(src-o-files) $(all-daemon) $(cf-local) diff --git a/nest/notify.c b/nest/notify.c deleted file mode 100644 index 874263e01..000000000 --- a/nest/notify.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * BIRD Internet Routing Daemon -- Notificators and Listeners - * - * (c) 2019 Maria Matejka - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#include "nest/bird.h" -#include "lib/resource.h" -#include "nest/notify.h" - -LISTENER_DECL(void); - -static void -listener_unsubscribe(resource *r) -{ - LISTENER(void) *L = (LISTENER(void) *) r; - rem_node(&(L->n)); - CALL(L->unsubscribe, L->self); -} - -struct resclass listener_class = { - .name = "Listener", - .size = sizeof(LISTENER(void)), - .free = listener_unsubscribe, - .dump = NULL, - .lookup = NULL, - .memsize = NULL, -}; diff --git a/nest/notify.h b/nest/notify.h index 6fd47fed2..4e006594b 100644 --- a/nest/notify.h +++ b/nest/notify.h @@ -10,25 +10,43 @@ #define _BIRD_NOTIFY_H_ #include "lib/resource.h" -#include "lib/lists.h" +#include "lib/tlists.h" #define LISTENER(stype) struct listener__##stype -#define LISTENER_DECL(stype) LISTENER(stype) { \ +#define LISTENER_DEF(stype) \ + TLIST_DEF(listener__##stype); \ +LISTENER(stype) { \ resource r; \ - node n; \ + TNODE(listener__##stype) n; \ void *self; \ void (*unsubscribe)(void *self); \ void (*notify)(void *self, const stype *data); \ -}; +}; \ +extern struct resclass LISTENER_CLASS(stype) -extern struct resclass listener_class; +#define LISTENERS(stype) TLIST(listener__##stype) + +#define LISTENER_CLASS(stype) listener_class__##stype +#define LISTENER_CLASS_DEF(stype) static void listener_unsubscribe__##stype(resource *r) { \ + LISTENER(stype) *L = (LISTENER(stype) *) r; \ + TREM_NODE(listener__##stype, L->n); \ + CALL(L->unsubscribe, L->self); \ +} \ +struct resclass LISTENER_CLASS(stype) = { \ + .name = "Listener " #stype, \ + .size = sizeof(LISTENER(stype)), \ + .free = listener_unsubscribe__##stype, \ +} + +#define INIT_LISTENERS(stype, sender) INIT_TLIST(listener__##stype, sender) #define SUBSCRIBE(stype, pool, sender, _self, _notify, _unsubscribe) ({ \ - LISTENER(stype) *L = ralloc(pool, &listener_class); \ + LISTENER(stype) *L = ralloc(pool, &listener_class__##stype); \ L->notify = _notify; \ L->unsubscribe = _unsubscribe; \ L->self = _self; \ - add_tail(&(sender), &(L->n)); \ + L->n.self = L; \ + TADD_TAIL(listener__##stype, sender, L->n); \ L; \ }) @@ -39,18 +57,14 @@ extern struct resclass listener_class; } while (0) #define UNNOTIFY(stype, sender) do { \ - LISTENER(stype) *L; \ - node *x, *y; \ - WALK_LIST2_DELSAFE(L, x, y, sender, n) \ - rfree(L); \ + WALK_TLIST_DELSAFE(listener__##stype, L, sender) \ + rfree(L->self); \ } 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); \ + WALK_TLIST_DELSAFE(listener__##stype, L, sender) \ + L->self->notify(L->self->self, _d); \ } while (0) #endif diff --git a/nest/route.h b/nest/route.h index 9a946d2d5..9ed87fa02 100644 --- a/nest/route.h +++ b/nest/route.h @@ -146,12 +146,15 @@ struct rtable_config { byte sorted; /* Routes of network are sorted according to rte_better() */ }; +typedef struct rt_notify rt_notify_data; +LISTENER_DEF(rt_notify_data); + typedef struct rtable { node n; /* Node in list of all tables */ struct fib fib; char *name; /* Name of this table */ list channels; /* List of attached channels (struct channel) */ - list listeners; /* List of attached listeners (struct listener) */ + LISTENERS(rt_notify_data) listeners; /* List of attached listeners */ uint addr_type; /* Type of address data stored in table (NET_*) */ int pipe_busy; /* Pipe loop detection */ int use_count; /* Number of protocols using this table */ @@ -327,8 +330,6 @@ typedef struct rt_notify { 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 6817df2d7..39ae6e63a 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -864,6 +864,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed rte_free(old_changed_free); } +LISTENER_CLASS_DEF(rt_notify_data); /** * rte_announce - announce a routing table change @@ -1738,7 +1739,7 @@ rt_setup(pool *p, rtable *t, struct rtable_config *cf) t->addr_type = cf->addr_type; fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL); init_list(&t->channels); - init_list(&t->listeners); + INIT_LISTENERS(rt_notify_data, t->listeners); t->rt_event = ev_new_init(p, rt_event, t); t->gc_time = current_time();