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);
}
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 */
#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);
-}
#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
#include "lib/resource.h"
#include "lib/net.h"
+#include "nest/notify.h"
+
struct ea_list;
struct protocol;
struct proto;
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;
.before_old = before_old,
};
- notify(&(tab->listeners), &rtn);
+ NOTIFY(rt_notify_data, tab->listeners, &rtn);
}
static inline int
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);