Commit a8722345 authored by Rusty Russell's avatar Rusty Russell

tal: allow notifiers on NULL.

A destructor on NULL doesn't make sense, but notifiers (eg. new children)
do.  We fix up a mistake in run-notifier (comparing ctx with itself) and
loose typing in tal.c's tal_add_notifier_ too.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent d1a951b8
...@@ -191,14 +191,14 @@ static void *from_tal_hdr(const struct tal_hdr *hdr) ...@@ -191,14 +191,14 @@ static void *from_tal_hdr(const struct tal_hdr *hdr)
return (void *)(hdr + 1); return (void *)(hdr + 1);
} }
#ifdef TAL_DEBUG static void *from_tal_hdr_or_null(const struct tal_hdr *hdr)
static void *from_tal_hdr_or_null(struct tal_hdr *hdr)
{ {
if (hdr == &null_parent.hdr) if (hdr == &null_parent.hdr)
return NULL; return NULL;
return from_tal_hdr(hdr); return from_tal_hdr(hdr);
} }
#ifdef TAL_DEBUG
static struct tal_hdr *debug_tal(struct tal_hdr *tal) static struct tal_hdr *debug_tal(struct tal_hdr *tal)
{ {
tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG "); tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG ");
...@@ -234,7 +234,7 @@ static void notify(const struct tal_hdr *ctx, ...@@ -234,7 +234,7 @@ static void notify(const struct tal_hdr *ctx,
else else
n->u.destroy(from_tal_hdr(ctx)); n->u.destroy(from_tal_hdr(ctx));
} else } else
n->u.notifyfn(from_tal_hdr(ctx), type, n->u.notifyfn(from_tal_hdr_or_null(ctx), type,
(void *)info); (void *)info);
} }
} }
...@@ -528,7 +528,7 @@ bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg) ...@@ -528,7 +528,7 @@ bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg)
bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types, bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types,
void (*callback)(tal_t *, enum tal_notify_type, void *)) void (*callback)(tal_t *, enum tal_notify_type, void *))
{ {
tal_t *t = debug_tal(to_tal_hdr(ctx)); struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx));
struct notifier *n; struct notifier *n;
assert(types); assert(types);
...@@ -556,7 +556,7 @@ bool tal_del_notifier_(const tal_t *ctx, ...@@ -556,7 +556,7 @@ bool tal_del_notifier_(const tal_t *ctx,
void (*callback)(tal_t *, enum tal_notify_type, void *), void (*callback)(tal_t *, enum tal_notify_type, void *),
bool match_extra_arg, void *extra_arg) bool match_extra_arg, void *extra_arg)
{ {
struct tal_hdr *t = debug_tal(to_tal_hdr(ctx)); struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx));
enum tal_notify_type types; enum tal_notify_type types;
types = del_notifier_property(t, callback, match_extra_arg, extra_arg); types = del_notifier_property(t, callback, match_extra_arg, extra_arg);
......
...@@ -227,7 +227,7 @@ enum tal_notify_type { ...@@ -227,7 +227,7 @@ enum tal_notify_type {
/** /**
* tal_add_notifier - add a callback function when this context changes. * tal_add_notifier - add a callback function when this context changes.
* @ptr: The tal allocated object. * @ptr: The tal allocated object, or NULL.
* @types: Bitwise OR of the types the callback is interested in. * @types: Bitwise OR of the types the callback is interested in.
* @callback: the function to call. * @callback: the function to call.
* *
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
static enum tal_notify_type expect; static enum tal_notify_type expect;
static void *expect_info; static void *expect_info;
static char *ctx; static char *ctx;
static unsigned int notified1, notified2; static unsigned int notified1, notified2, notified_null;
/* Make sure we always move on resize. */ /* Make sure we always move on resize. */
static void *my_realloc(void *old, size_t size) static void *my_realloc(void *old, size_t size)
...@@ -20,9 +20,9 @@ static void *my_realloc(void *old, size_t size) ...@@ -20,9 +20,9 @@ static void *my_realloc(void *old, size_t size)
return new; return new;
} }
static void notify1(char *p UNNEEDED, enum tal_notify_type notify, void *info) static void notify1(char *p, enum tal_notify_type notify, void *info)
{ {
ok1(ctx == ctx); ok1(p == ctx);
ok1(notify == expect); ok1(notify == expect);
if (expect_info == &expect_info) if (expect_info == &expect_info)
expect_info = info; expect_info = info;
...@@ -38,6 +38,17 @@ static void notify2(char *ctx UNNEEDED, ...@@ -38,6 +38,17 @@ static void notify2(char *ctx UNNEEDED,
notified2++; notified2++;
} }
static void notify_null(void *p, enum tal_notify_type notify, void *info)
{
ok1(p == NULL);
ok1(notify == expect);
if (expect_info == &expect_info)
expect_info = info;
else
ok1(info == expect_info);
notified_null++;
}
static bool seen_move, seen_resize; static bool seen_move, seen_resize;
static void resize_notifier(char *p, enum tal_notify_type notify, void *info) static void resize_notifier(char *p, enum tal_notify_type notify, void *info)
{ {
...@@ -62,7 +73,7 @@ int main(void) ...@@ -62,7 +73,7 @@ int main(void)
{ {
char *child, *new_ctx; char *child, *new_ctx;
plan_tests(56); plan_tests(65);
ctx = tal(NULL, char); ctx = tal(NULL, char);
ok1(tal_add_notifier(ctx, 511, notify1)); ok1(tal_add_notifier(ctx, 511, notify1));
...@@ -119,6 +130,20 @@ int main(void) ...@@ -119,6 +130,20 @@ int main(void)
ok1(notified1 == 7); ok1(notified1 == 7);
ok1(notified2 == 1); ok1(notified2 == 1);
/* Notifiers on NULL work, too. */
ok1(tal_add_notifier(NULL, TAL_NOTIFY_ADD_CHILD|TAL_NOTIFY_DEL_CHILD,
notify_null));
expect = TAL_NOTIFY_ADD_CHILD;
expect_info = &expect_info;
child = tal(NULL, char);
ok1(notified_null == 1);
expect = TAL_NOTIFY_DEL_CHILD;
expect_info = child;
tal_free(child);
ok1(notified_null == 2);
ok1(tal_del_notifier(NULL, notify_null));
tal_set_backend(NULL, my_realloc, NULL, NULL); tal_set_backend(NULL, my_realloc, NULL, NULL);
ctx = new_ctx = tal(NULL, char); ctx = new_ctx = tal(NULL, char);
ok1(tal_add_notifier(new_ctx, 511, resize_notifier)); ok1(tal_add_notifier(new_ctx, 511, resize_notifier));
......
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