diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-09-28 11:54:17 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:59:26 -0500 |
commit | 8ae2cd82caaf8762e73499a1744c63c42a5b9fe6 (patch) | |
tree | a3aedd4910cb254e9e6aa16b5a058cc3b0563a6c /source4/lib/talloc.c | |
parent | 0a93af206c723be75de55db5d4da2e8d31a17c54 (diff) | |
download | samba-8ae2cd82caaf8762e73499a1744c63c42a5b9fe6.tar.gz samba-8ae2cd82caaf8762e73499a1744c63c42a5b9fe6.tar.bz2 samba-8ae2cd82caaf8762e73499a1744c63c42a5b9fe6.zip |
r2718: - added a talloc_unreference() function as requested by metze.
- added documentation for talloc_unreference()
- made the abandoned child logic in talloc_free() clearer and more consistent
(This used to be commit a87584c8e3fb06cd3ff29a918f681b5c6c32b9ff)
Diffstat (limited to 'source4/lib/talloc.c')
-rw-r--r-- | source4/lib/talloc.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index d0056d7b2a..bb2ed9449c 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -170,6 +170,34 @@ void *talloc_reference(const void *context, const void *ptr) return handle->ptr; } +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +void *talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (context == NULL) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *tc2 = talloc_chunk_from_ptr(h); + const void *parent = tc2->parent?tc2->parent+1:null_context; + if (parent == context) break; + } + if (h == NULL) { + return NULL; + } + + talloc_set_destructor(h, NULL); + DLIST_REMOVE(tc->refs, h); + talloc_free(h); + return discard_const(ptr); +} /* add a name to an existing pointer - va_list version @@ -318,8 +346,21 @@ int talloc_free(void *ptr) } while (tc->child) { - talloc_free(talloc_steal(tc->parent?tc->parent+1:null_context, - tc->child+1)); + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = tc->child+1; + const void *new_parent = null_context; + if (tc->child->refs) { + struct talloc_chunk *ref = talloc_chunk_from_ptr(tc->child->refs); + if (ref->parent) new_parent = ref->parent+1; + } + if (new_parent == null_context && tc->parent) { + new_parent = tc->parent+1; + } + talloc_free(talloc_steal(new_parent, child)); } if (tc->parent) { |