0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-11 03:21:53 +00:00

Subscribe/Notify: The notification data is typed.

This commit is contained in:
Maria Matejka 2019-03-11 22:23:20 +01:00
parent 370958afc2
commit bb623f0ae3
5 changed files with 54 additions and 57 deletions

View File

@ -55,12 +55,12 @@ void (*bt_assert_hook)(int result, struct f_inst *assert);
struct filter_roa_reloader { struct filter_roa_reloader {
node n; node n;
struct listener *L; LISTENER(rt_notify_data) *L;
struct rtable *roa_table; struct rtable *roa_table;
struct filter_slot *slot; 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; struct filter_roa_reloader *frr = self;
frr->slot->reloader(frr->slot); 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->roa_table = roa_table;
frr->slot = slot; frr->slot = slot;
add_tail(&(slot->notifiers), &(frr->n)); 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 */ static struct adata undef_adata; /* adata of length 0 used for undefined */

View File

@ -10,63 +10,21 @@
#include "lib/resource.h" #include "lib/resource.h"
#include "nest/notify.h" #include "nest/notify.h"
struct listener { LISTENER_DECL(void);
resource r;
node n;
void (*notify)(void *self, const void *data);
void (*unsubscribe)(void *self);
void *self;
};
static void static void
listener_unsubscribe(resource *r) listener_unsubscribe(resource *r)
{ {
struct listener *L = (struct listener *) r; LISTENER(void) *L = (LISTENER(void) *) r;
rem_node(&(L->n)); rem_node(&(L->n));
CALL(L->unsubscribe, L->self); CALL(L->unsubscribe, L->self);
} }
static struct resclass listener_class = { struct resclass listener_class = {
.name = "Listener", .name = "Listener",
.size = sizeof(struct listener), .size = sizeof(LISTENER(void)),
.free = listener_unsubscribe, .free = listener_unsubscribe,
.dump = NULL, .dump = NULL,
.lookup = NULL, .lookup = NULL,
.memsize = 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);
}

View File

@ -12,11 +12,45 @@
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/lists.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); extern struct resclass listener_class;
void unsubscribe(struct listener *L);
void unsubscribe_all(list *sender); #define SUBSCRIBE(stype, pool, sender, _self, _notify, _unsubscribe) ({ \
void notify(list *sender, const void *data); 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 #endif

View File

@ -13,6 +13,8 @@
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/net.h" #include "lib/net.h"
#include "nest/notify.h"
struct ea_list; struct ea_list;
struct protocol; struct protocol;
struct proto; struct proto;
@ -320,10 +322,12 @@ void rt_reload_channel_abort(struct channel *c);
void rt_prune_sync(rtable *t, int all); void rt_prune_sync(rtable *t, int all);
struct rtable_config *rt_new_table(struct symbol *s, uint addr_type); struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
struct rt_notify { typedef struct rt_notify {
struct network *net; struct network *net;
rte *new, *old, *new_best, *old_best, *before_old; 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 */ /* Default limit for ECMP next hops, defined in sysdep code */
extern const int rt_default_ecmp; extern const int rt_default_ecmp;

View File

@ -951,7 +951,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old,
.before_old = before_old, .before_old = before_old,
}; };
notify(&(tab->listeners), &rtn); NOTIFY(rt_notify_data, tab->listeners, &rtn);
} }
static inline int static inline int
@ -2173,6 +2173,7 @@ rt_unlock_table(rtable *r)
r->config->table = NULL; r->config->table = NULL;
if (r->hostcache) if (r->hostcache)
rt_free_hostcache(r); rt_free_hostcache(r);
UNNOTIFY(rt_notify_data, r->listeners);
rem_node(&r->n); rem_node(&r->n);
fib_free(&r->fib); fib_free(&r->fib);
rfree(r->rt_event); rfree(r->rt_event);