Commit 68b5c2c8 authored by Rusty Russell's avatar Rusty Russell

tal: use notifier infrastructure for destructors.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent d73a2bcb
...@@ -13,10 +13,11 @@ ...@@ -13,10 +13,11 @@
//#define TAL_DEBUG 1 //#define TAL_DEBUG 1
#define NOTIFY_IS_DESTRUCTOR 512
/* 32-bit type field, first byte 0 in either endianness. */ /* 32-bit type field, first byte 0 in either endianness. */
enum prop_type { enum prop_type {
CHILDREN = 0x00c1d500, CHILDREN = 0x00c1d500,
DESTRUCTOR = 0x00de5700,
NAME = 0x00111100, NAME = 0x00111100,
NOTIFIER = 0x00071f00 NOTIFIER = 0x00071f00
}; };
...@@ -38,11 +39,6 @@ struct children { ...@@ -38,11 +39,6 @@ struct children {
struct list_head children; /* Head of siblings. */ struct list_head children; /* Head of siblings. */
}; };
struct destructor {
struct prop_hdr hdr; /* DESTRUCTOR */
void (*destroy)(void *me);
};
struct name { struct name {
struct prop_hdr hdr; /* NAME */ struct prop_hdr hdr; /* NAME */
char name[]; char name[];
...@@ -51,7 +47,10 @@ struct name { ...@@ -51,7 +47,10 @@ struct name {
struct notifier { struct notifier {
struct prop_hdr hdr; /* NOTIFIER */ struct prop_hdr hdr; /* NOTIFIER */
enum tal_notify_type types; enum tal_notify_type types;
void (*notifyfn)(tal_t *, enum tal_notify_type, void *); union {
void (*notifyfn)(tal_t *, enum tal_notify_type, void *);
void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */
} u;
}; };
static struct { static struct {
...@@ -214,8 +213,13 @@ static void notify(const struct tal_hdr *ctx, ...@@ -214,8 +213,13 @@ static void notify(const struct tal_hdr *ctx,
if (p->type != NOTIFIER) if (p->type != NOTIFIER)
continue; continue;
n = (struct notifier *)p; n = (struct notifier *)p;
if (n->types & type) if (n->types & type) {
n->notifyfn(from_tal_hdr(ctx), type, (void *)info); if (n->types & NOTIFY_IS_DESTRUCTOR)
n->u.destroy(from_tal_hdr(ctx));
else
n->u.notifyfn(from_tal_hdr(ctx), type,
(void *)info);
}
} }
} }
...@@ -272,39 +276,6 @@ static void init_property(struct prop_hdr *hdr, ...@@ -272,39 +276,6 @@ static void init_property(struct prop_hdr *hdr,
parent->prop = hdr; parent->prop = hdr;
} }
static struct destructor *add_destructor_property(struct tal_hdr *t,
void (*destroy)(void *))
{
struct destructor *prop = allocate(sizeof(*prop));
if (prop) {
init_property(&prop->hdr, t, DESTRUCTOR);
prop->destroy = destroy;
}
return prop;
}
static bool del_destructor_property(struct tal_hdr *t,
void (*destroy)(void *))
{
struct prop_hdr **p;
for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
struct destructor *d;
if (is_literal(*p))
break;
if ((*p)->type != DESTRUCTOR)
continue;
d = (struct destructor *)*p;
if (d->destroy == destroy) {
*p = (*p)->next;
freefn(d);
return true;
}
}
return false;
}
static struct notifier *add_notifier_property(struct tal_hdr *t, static struct notifier *add_notifier_property(struct tal_hdr *t,
enum tal_notify_type types, enum tal_notify_type types,
void (*fn)(void *, void (*fn)(void *,
...@@ -315,7 +286,7 @@ static struct notifier *add_notifier_property(struct tal_hdr *t, ...@@ -315,7 +286,7 @@ static struct notifier *add_notifier_property(struct tal_hdr *t,
if (prop) { if (prop) {
init_property(&prop->hdr, t, NOTIFIER); init_property(&prop->hdr, t, NOTIFIER);
prop->types = types; prop->types = types;
prop->notifyfn = fn; prop->u.notifyfn = fn;
} }
return prop; return prop;
} }
...@@ -334,7 +305,7 @@ static bool del_notifier_property(struct tal_hdr *t, ...@@ -334,7 +305,7 @@ static bool del_notifier_property(struct tal_hdr *t,
if ((*p)->type != NOTIFIER) if ((*p)->type != NOTIFIER)
continue; continue;
n = (struct notifier *)*p; n = (struct notifier *)*p;
if (n->notifyfn == fn) { if (n->u.notifyfn == fn) {
*p = (*p)->next; *p = (*p)->next;
freefn(n); freefn(n);
return true; return true;
...@@ -396,14 +367,6 @@ static void del_tree(struct tal_hdr *t, const tal_t *orig) ...@@ -396,14 +367,6 @@ static void del_tree(struct tal_hdr *t, const tal_t *orig)
set_destroying_bit(&t->parent_child); set_destroying_bit(&t->parent_child);
/* Carefully call destructors, removing as we go. */
while ((prop = find_property_ptr(t, DESTRUCTOR))) {
struct destructor *d = (struct destructor *)*prop;
d->destroy(from_tal_hdr(t));
*prop = d->hdr.next;
freefn(d);
}
/* Call free notifiers. */ /* Call free notifiers. */
notify(t, TAL_NOTIFY_FREE, (tal_t *)orig); notify(t, TAL_NOTIFY_FREE, (tal_t *)orig);
...@@ -489,7 +452,8 @@ void *tal_steal_(const tal_t *new_parent, const tal_t *ctx) ...@@ -489,7 +452,8 @@ void *tal_steal_(const tal_t *new_parent, const tal_t *ctx)
bool tal_add_destructor_(tal_t *ctx, void (*destroy)(void *me)) bool tal_add_destructor_(tal_t *ctx, void (*destroy)(void *me))
{ {
tal_t *t = debug_tal(to_tal_hdr(ctx)); tal_t *t = debug_tal(to_tal_hdr(ctx));
return add_destructor_property(t, destroy); return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR,
(void *)destroy);
} }
bool tal_add_notifier_(tal_t *ctx, enum tal_notify_type types, bool tal_add_notifier_(tal_t *ctx, enum tal_notify_type types,
...@@ -529,8 +493,7 @@ bool tal_del_notifier_(tal_t *ctx, ...@@ -529,8 +493,7 @@ bool tal_del_notifier_(tal_t *ctx,
bool tal_del_destructor_(tal_t *ctx, void (*destroy)(void *me)) bool tal_del_destructor_(tal_t *ctx, void (*destroy)(void *me))
{ {
struct tal_hdr *t = debug_tal(to_tal_hdr(ctx)); return tal_del_notifier_(ctx, (void *)destroy);
return del_destructor_property(t, destroy);
} }
bool tal_set_name_(tal_t *ctx, const char *name, bool literal) bool tal_set_name_(tal_t *ctx, const char *name, bool literal)
...@@ -799,7 +762,6 @@ static void dump_node(unsigned int indent, const struct tal_hdr *t) ...@@ -799,7 +762,6 @@ static void dump_node(unsigned int indent, const struct tal_hdr *t)
printf("%p", t); printf("%p", t);
for (p = t->prop; p; p = p->next) { for (p = t->prop; p; p = p->next) {
struct children *c; struct children *c;
struct destructor *d;
struct name *n; struct name *n;
struct notifier *no; struct notifier *no;
if (is_literal(p)) { if (is_literal(p)) {
...@@ -813,17 +775,13 @@ static void dump_node(unsigned int indent, const struct tal_hdr *t) ...@@ -813,17 +775,13 @@ static void dump_node(unsigned int indent, const struct tal_hdr *t)
p, c->parent, p, c->parent,
c->children.n.prev, c->children.n.next); c->children.n.prev, c->children.n.next);
break; break;
case DESTRUCTOR:
d = (struct destructor *)p;
printf(" DESTRUCTOR(%p):fn=%p", p, d->destroy);
break;
case NAME: case NAME:
n = (struct name *)p; n = (struct name *)p;
printf(" NAME(%p):%s", p, n->name); printf(" NAME(%p):%s", p, n->name);
break; break;
case NOTIFIER: case NOTIFIER:
no = (struct notifier *)p; no = (struct notifier *)p;
printf(" NOTIFIER(%p):fn=%p", p, no->notifyfn); printf(" NOTIFIER(%p):fn=%p", p, no->u.notifyfn);
break; break;
default: default:
printf(" **UNKNOWN(%p):%i**", p, p->type); printf(" **UNKNOWN(%p):%i**", p, p->type);
...@@ -898,7 +856,6 @@ static bool check_node(struct children *parent_child, ...@@ -898,7 +856,6 @@ static bool check_node(struct children *parent_child,
"has two child nodes"); "has two child nodes");
children = (struct children *)p; children = (struct children *)p;
break; break;
case DESTRUCTOR:
case NOTIFIER: case NOTIFIER:
break; break;
case NAME: case NAME:
......
...@@ -127,6 +127,9 @@ void *tal_free(const tal_t *p); ...@@ -127,6 +127,9 @@ void *tal_free(const tal_t *p);
* @ptr: The tal allocated object. * @ptr: The tal allocated object.
* @function: the function to call before it's freed. * @function: the function to call before it's freed.
* *
* This is a more convenient form of tal_add_notifier(@ptr,
* TAL_NOTIFY_FREE, ...), in that the function prototype takes only @ptr.
*
* Note that this can only fail if your allocfn fails and your errorfn returns. * Note that this can only fail if your allocfn fails and your errorfn returns.
*/ */
#define tal_add_destructor(ptr, function) \ #define tal_add_destructor(ptr, function) \
...@@ -187,9 +190,10 @@ enum tal_notify_type { ...@@ -187,9 +190,10 @@ enum tal_notify_type {
* not called when this context is tal_free()d: TAL_NOTIFY_FREE is * not called when this context is tal_free()d: TAL_NOTIFY_FREE is
* considered sufficient for that case. * considered sufficient for that case.
* *
* TAL_NOTIFY_ADD_NOTIFIER/TAL_NOTIFIER_DEL_NOTIFIER are called when * TAL_NOTIFY_ADD_NOTIFIER/TAL_NOTIFIER_DEL_NOTIFIER are called when a
* a notifier is added or removed (not for this notifier): @info is the * notifier is added or removed (not for this notifier): @info is the
* callback. * callback. This is also called for tal_add_destructor and
* tal_del_destructor.
*/ */
#define tal_add_notifier(ptr, types, callback) \ #define tal_add_notifier(ptr, types, callback) \
tal_add_notifier_((ptr), (types), \ tal_add_notifier_((ptr), (types), \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment