]> git.ozlabs.org Git - ccan/blobdiff - ccan/tal/tal.c
htable: add htable_type _delval.
[ccan] / ccan / tal / tal.c
index 342cce34f03897b7568ae6080c293d52830660dd..a49541114ff863128dd03a1429fa84c1d4e06ffb 100644 (file)
@@ -53,7 +53,7 @@ struct name {
 struct notifier {
        struct prop_hdr hdr; /* NOTIFIER */
        enum tal_notify_type types;
-       union {
+       union notifier_cb {
                void (*notifyfn)(tal_t *, enum tal_notify_type, void *);
                void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */
                void (*destroy2)(tal_t *, void *); /* If NOTIFY_EXTRA_ARG */
@@ -191,14 +191,14 @@ static void *from_tal_hdr(const struct tal_hdr *hdr)
        return (void *)(hdr + 1);
 }
 
-#ifdef TAL_DEBUG
-static void *from_tal_hdr_or_null(struct tal_hdr *hdr)
+static void *from_tal_hdr_or_null(const struct tal_hdr *hdr)
 {
        if (hdr == &null_parent.hdr)
                return NULL;
        return from_tal_hdr(hdr);
 }
 
+#ifdef TAL_DEBUG
 static struct tal_hdr *debug_tal(struct tal_hdr *tal)
 {
        tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG ");
@@ -228,13 +228,18 @@ static void notify(const struct tal_hdr *ctx,
                if (n->types & type) {
                        errno = saved_errno;
                        if (n->types & NOTIFY_IS_DESTRUCTOR) {
+                               /* Blatt this notifier in case it tries to
+                                * tal_del_destructor() from inside */
+                               union notifier_cb cb = n->u;
+                               /* It's a union, so this NULLs destroy2 too! */
+                               n->u.destroy = NULL;
                                if (n->types & NOTIFY_EXTRA_ARG)
-                                       n->u.destroy2(from_tal_hdr(ctx),
-                                                     EXTRA_ARG(n));
+                                       cb.destroy2(from_tal_hdr(ctx),
+                                                   EXTRA_ARG(n));
                                else
-                                       n->u.destroy(from_tal_hdr(ctx));
+                                       cb.destroy(from_tal_hdr(ctx));
                        } else
-                               n->u.notifyfn(from_tal_hdr(ctx), type,
+                               n->u.notifyfn(from_tal_hdr_or_null(ctx), type,
                                              (void *)info);
                }
        }
@@ -385,6 +390,8 @@ static void del_tree(struct tal_hdr *t, const tal_t *orig, int saved_errno)
 {
        struct prop_hdr **prop, *p, *next;
 
+       assert(!taken(from_tal_hdr(t)));
+
         /* Already being destroyed?  Don't loop. */
         if (unlikely(get_destroying_bit(t->parent_child)))
                 return;
@@ -528,7 +535,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,
                       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;
 
        assert(types);
@@ -556,7 +563,7 @@ bool tal_del_notifier_(const tal_t *ctx,
                       void (*callback)(tal_t *, enum tal_notify_type, void *),
                       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;
 
         types = del_notifier_property(t, callback, match_extra_arg, extra_arg);
@@ -710,6 +717,10 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear)
                /* Fix up linked list pointers. */
                t->list.next->prev = t->list.prev->next = &t->list;
 
+               /* Copy take() property. */
+               if (taken(from_tal_hdr(old_t)))
+                       take(from_tal_hdr(t));
+
                /* Fix up child property's parent pointer. */
                child = find_property(t, CHILDREN);
                if (child) {