talloc_link.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include <ccan/list/list.h>
  2. #include <ccan/talloc/talloc.h>
  3. #include <ccan/talloc_link/talloc_link.h>
  4. #include <assert.h>
  5. /* Fake parent, if they care. */
  6. static void *talloc_links = NULL;
  7. /* This is the parent of the linked object, so we can implement delink. */
  8. struct talloc_linked {
  9. struct list_head links;
  10. const void *obj;
  11. };
  12. /* This is a child of the linker, but not a parent of ref. */
  13. struct talloc_link {
  14. struct list_node list;
  15. struct talloc_linked *linked;
  16. };
  17. static int destroy_link(struct talloc_link *link)
  18. {
  19. list_del(&link->list);
  20. if (list_empty(&link->linked->links))
  21. talloc_free(link->linked);
  22. return 0;
  23. }
  24. static bool add_link(const void *ctx, struct talloc_linked *linked)
  25. {
  26. struct talloc_link *link = talloc(ctx, struct talloc_link);
  27. if (!link)
  28. return false;
  29. link->linked = linked;
  30. list_add(&linked->links, &link->list);
  31. talloc_set_destructor(link, destroy_link);
  32. return true;
  33. }
  34. void *_talloc_linked(const void *ctx, const void *newobj)
  35. {
  36. struct talloc_linked *linked;
  37. if (talloc_parent(newobj)) {
  38. /* Assume leak reporting is on: create dummy parent. */
  39. if (!talloc_links)
  40. talloc_links = talloc_named_const(NULL, 0,
  41. "talloc_links");
  42. /* This should now have same pseudo-NULL parent. */
  43. assert(talloc_parent(newobj) == talloc_parent(talloc_links));
  44. }
  45. linked = talloc(talloc_links, struct talloc_linked);
  46. if (!linked) {
  47. talloc_free(newobj);
  48. return NULL;
  49. }
  50. list_head_init(&linked->links);
  51. linked->obj = talloc_steal(linked, newobj);
  52. if (!add_link(ctx, linked)) {
  53. talloc_free(linked);
  54. return NULL;
  55. }
  56. return (void *)newobj;
  57. }
  58. void *_talloc_link(const void *ctx, const void *obj)
  59. {
  60. struct talloc_linked *linked;
  61. linked = talloc_get_type(talloc_parent(obj), struct talloc_linked);
  62. assert(!list_empty(&linked->links));
  63. return add_link(ctx, linked) ? (void *)obj : NULL;
  64. }
  65. void talloc_delink(const void *ctx, const void *obj)
  66. {
  67. struct talloc_linked *linked;
  68. struct talloc_link *i;
  69. if (!obj)
  70. return;
  71. linked = talloc_get_type(talloc_parent(obj), struct talloc_linked);
  72. list_for_each(&linked->links, i, list) {
  73. if (talloc_is_parent(i, ctx)) {
  74. talloc_free(i);
  75. return;
  76. }
  77. }
  78. abort();
  79. }