|
|
@@ -14,6 +14,7 @@
|
|
|
//#define TAL_DEBUG 1
|
|
|
|
|
|
#define NOTIFY_IS_DESTRUCTOR 512
|
|
|
+#define NOTIFY_EXTRA_ARG 1024
|
|
|
|
|
|
/* 32-bit type field, first byte 0 in either endianness. */
|
|
|
enum prop_type {
|
|
|
@@ -56,9 +57,18 @@ struct notifier {
|
|
|
union {
|
|
|
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 */
|
|
|
} u;
|
|
|
};
|
|
|
|
|
|
+/* Extra arg */
|
|
|
+struct notifier_extra_arg {
|
|
|
+ struct notifier n;
|
|
|
+ void *arg;
|
|
|
+};
|
|
|
+
|
|
|
+#define EXTRA_ARG(n) (((struct notifier_extra_arg *)(n))->arg)
|
|
|
+
|
|
|
static struct {
|
|
|
struct tal_hdr hdr;
|
|
|
struct children c;
|
|
|
@@ -218,9 +228,13 @@ static void notify(const struct tal_hdr *ctx,
|
|
|
n = (struct notifier *)p;
|
|
|
if (n->types & type) {
|
|
|
errno = saved_errno;
|
|
|
- if (n->types & NOTIFY_IS_DESTRUCTOR)
|
|
|
- n->u.destroy(from_tal_hdr(ctx));
|
|
|
- else
|
|
|
+ if (n->types & NOTIFY_IS_DESTRUCTOR) {
|
|
|
+ if (n->types & NOTIFY_EXTRA_ARG)
|
|
|
+ n->u.destroy2(from_tal_hdr(ctx),
|
|
|
+ EXTRA_ARG(n));
|
|
|
+ else
|
|
|
+ n->u.destroy(from_tal_hdr(ctx));
|
|
|
+ } else
|
|
|
n->u.notifyfn(from_tal_hdr(ctx), type,
|
|
|
(void *)info);
|
|
|
}
|
|
|
@@ -276,13 +290,22 @@ static struct notifier *add_notifier_property(struct tal_hdr *t,
|
|
|
enum tal_notify_type types,
|
|
|
void (*fn)(void *,
|
|
|
enum tal_notify_type,
|
|
|
- void *))
|
|
|
+ void *),
|
|
|
+ void *extra_arg)
|
|
|
{
|
|
|
- struct notifier *prop = allocate(sizeof(*prop));
|
|
|
+ struct notifier *prop;
|
|
|
+
|
|
|
+ if (types & NOTIFY_EXTRA_ARG)
|
|
|
+ prop = allocate(sizeof(struct notifier_extra_arg));
|
|
|
+ else
|
|
|
+ prop = allocate(sizeof(struct notifier));
|
|
|
+
|
|
|
if (prop) {
|
|
|
init_property(&prop->hdr, t, NOTIFIER);
|
|
|
prop->types = types;
|
|
|
prop->u.notifyfn = fn;
|
|
|
+ if (types & NOTIFY_EXTRA_ARG)
|
|
|
+ EXTRA_ARG(prop) = extra_arg;
|
|
|
}
|
|
|
return prop;
|
|
|
}
|
|
|
@@ -290,24 +313,33 @@ static struct notifier *add_notifier_property(struct tal_hdr *t,
|
|
|
static enum tal_notify_type del_notifier_property(struct tal_hdr *t,
|
|
|
void (*fn)(tal_t *,
|
|
|
enum tal_notify_type,
|
|
|
- void *))
|
|
|
+ void *),
|
|
|
+ bool match_extra_arg,
|
|
|
+ void *extra_arg)
|
|
|
{
|
|
|
struct prop_hdr **p;
|
|
|
|
|
|
for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
|
|
|
struct notifier *n;
|
|
|
+ enum tal_notify_type types;
|
|
|
|
|
|
if (is_literal(*p))
|
|
|
break;
|
|
|
if ((*p)->type != NOTIFIER)
|
|
|
continue;
|
|
|
n = (struct notifier *)*p;
|
|
|
- if (n->u.notifyfn == fn) {
|
|
|
- enum tal_notify_type types = n->types;
|
|
|
- *p = (*p)->next;
|
|
|
- freefn(n);
|
|
|
- return types & ~NOTIFY_IS_DESTRUCTOR;
|
|
|
- }
|
|
|
+ if (n->u.notifyfn != fn)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ types = n->types;
|
|
|
+ if ((types & NOTIFY_EXTRA_ARG)
|
|
|
+ && match_extra_arg
|
|
|
+ && extra_arg != EXTRA_ARG(n))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ *p = (*p)->next;
|
|
|
+ freefn(n);
|
|
|
+ return types & ~(NOTIFY_IS_DESTRUCTOR|NOTIFY_EXTRA_ARG);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -506,9 +538,19 @@ bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me))
|
|
|
{
|
|
|
tal_t *t = debug_tal(to_tal_hdr(ctx));
|
|
|
return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR,
|
|
|
- (void *)destroy);
|
|
|
+ (void *)destroy, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg),
|
|
|
+ void *arg)
|
|
|
+{
|
|
|
+ tal_t *t = debug_tal(to_tal_hdr(ctx));
|
|
|
+ return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR
|
|
|
+ |NOTIFY_EXTRA_ARG,
|
|
|
+ (void *)destroy, arg);
|
|
|
}
|
|
|
|
|
|
+/* We could support notifiers with an extra arg, but we didn't add to API */
|
|
|
bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types,
|
|
|
void (*callback)(tal_t *, enum tal_notify_type, void *))
|
|
|
{
|
|
|
@@ -523,7 +565,7 @@ bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types,
|
|
|
| TAL_NOTIFY_DEL_NOTIFIER)) == 0);
|
|
|
|
|
|
/* Don't call notifier about itself: set types after! */
|
|
|
- n = add_notifier_property(t, 0, callback);
|
|
|
+ n = add_notifier_property(t, 0, callback, NULL);
|
|
|
if (unlikely(!n))
|
|
|
return false;
|
|
|
|
|
|
@@ -537,12 +579,13 @@ bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types,
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
{
|
|
|
struct tal_hdr *t = debug_tal(to_tal_hdr(ctx));
|
|
|
enum tal_notify_type types;
|
|
|
|
|
|
- types = del_notifier_property(t, callback);
|
|
|
+ types = del_notifier_property(t, callback, match_extra_arg, extra_arg);
|
|
|
if (types) {
|
|
|
notify(t, TAL_NOTIFY_DEL_NOTIFIER, callback, 0);
|
|
|
if (types != TAL_NOTIFY_FREE)
|
|
|
@@ -554,7 +597,13 @@ bool tal_del_notifier_(const tal_t *ctx,
|
|
|
|
|
|
bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me))
|
|
|
{
|
|
|
- return tal_del_notifier_(ctx, (void *)destroy);
|
|
|
+ return tal_del_notifier_(ctx, (void *)destroy, false, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+bool tal_del_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg),
|
|
|
+ void *arg)
|
|
|
+{
|
|
|
+ return tal_del_notifier_(ctx, (void *)destroy, true, arg);
|
|
|
}
|
|
|
|
|
|
bool tal_set_name_(tal_t *ctx, const char *name, bool literal)
|