]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Subscribe/Notify: The notification data is typed.
authorMaria Matejka <mq@ucw.cz>
Mon, 11 Mar 2019 21:23:20 +0000 (22:23 +0100)
committerMaria Matejka <mq@ucw.cz>
Mon, 11 Mar 2019 21:23:20 +0000 (22:23 +0100)
filter/filter.c
nest/notify.c
nest/notify.h
nest/route.h
nest/rt-table.c

index 4eaf640504a0068c304681323ca4d6aa51feb1b5..43cb58871efec0726cba37870ee3bc474aa5a18f 100644 (file)
@@ -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 */
index fac1ac814baa1e856131349019049e568beda6c6..874263e01600c7684db0861fd3cf3be4b459d241 100644 (file)
 #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);
-}
index 22b67cc5b172cc8eba84fac688e51e0afdf4e271..6fd47fed28a0582bd5878a314594a0f041c2552c 100644 (file)
 #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
index 00747b6c5c5840ef524ca379f5041228fef1ac7c..9a946d2d5fb243bcaee71ffda7d65fd40c4b14da 100644 (file)
@@ -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;
index 0646ece3259a1835600c198fdddcac0bb00889fb..6817df2d77df68d1ccc5622a211133967aeb2a24 100644 (file)
@@ -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);