1 /* Licensed under GPLv2+ - see LICENSE file for details */
2 #include <ccan/list/list.h>
3 #include <ccan/talloc/talloc.h>
4 #include <ccan/talloc_link/talloc_link.h>
7 /* Fake parent, if they care. */
8 static void *talloc_links = NULL;
10 /* This is the parent of the linked object, so we can implement delink. */
11 struct talloc_linked {
12 struct list_head links;
16 /* This is a child of the linker, but not a parent of ref. */
18 struct list_node list;
19 struct talloc_linked *linked;
22 static int destroy_link(struct talloc_link *link)
24 list_del(&link->list);
25 if (list_empty(&link->linked->links))
26 talloc_free(link->linked);
30 static bool add_link(const void *ctx, struct talloc_linked *linked)
32 struct talloc_link *link = talloc(ctx, struct talloc_link);
36 link->linked = linked;
37 list_add(&linked->links, &link->list);
38 talloc_set_destructor(link, destroy_link);
42 void *_talloc_linked(const void *ctx, const void *newobj)
44 struct talloc_linked *linked;
46 if (talloc_parent(newobj)) {
47 /* Assume leak reporting is on: create dummy parent. */
49 talloc_links = talloc_named_const(NULL, 0,
51 /* This should now have same pseudo-NULL parent. */
52 assert(talloc_parent(newobj) == talloc_parent(talloc_links));
55 linked = talloc(talloc_links, struct talloc_linked);
60 list_head_init(&linked->links);
61 linked->obj = talloc_steal(linked, newobj);
63 if (!add_link(ctx, linked)) {
68 return (void *)newobj;
71 void *_talloc_link(const void *ctx, const void *obj)
73 struct talloc_linked *linked;
75 linked = talloc_get_type(talloc_parent(obj), struct talloc_linked);
76 assert(!list_empty(&linked->links));
77 return add_link(ctx, linked) ? (void *)obj : NULL;
80 void talloc_delink(const void *ctx, const void *obj)
82 struct talloc_linked *linked;
83 struct talloc_link *i;
88 linked = talloc_get_type(talloc_parent(obj), struct talloc_linked);
89 list_for_each(&linked->links, i, list) {
90 if (talloc_is_parent(i, ctx)) {