From 61a7dfc2371c65bce0bf15ef868b40921cd81756 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 05:13:00 +0000 Subject: r2675: added a convenience function void *talloc_reference(const void *context, const void *ptr); this function makes a secondary reference to ptr, and hangs it off the given context. This greatly simplifies some of the current reference counting code in the samr server and I suspect it will be widely used in other places too. the way you use it is like this: domain_state->connect_state = talloc_reference(domain_state, connect_state); that makes the element connect_state of domain_state a secondary reference to connect_state. The connect_state structure will then only be freed when both domain_state and the original connect_state go away, allowing you to free them independently and in any order. you could do this alrady using a talloc destructor, and that is what the samr server did previously, but that meant this construct was being reinvented in several places. So this convenience function sets up the destructor for you, giving a much more convenient and less error prone API. (This used to be commit dc5315086156644fad093cbe6b02d999adba8540) --- source4/lib/talloc.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index ce8f1c5272..55b97717c7 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -124,6 +124,41 @@ void talloc_increase_ref_count(const void *ptr) tc->ref_count++; } +/* + helper for talloc_reference() +*/ +static int talloc_reference_destructor(void *ptr) +{ + void **handle = ptr; + talloc_free(*handle); + return 0; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *talloc_reference(const void *context, const void *ptr) +{ + void **handle; + handle = _talloc(context, sizeof(void *)); + if (handle == NULL) { + return NULL; + } + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + talloc_increase_ref_count(ptr); + *handle = discard_const(ptr); + return *handle; +} + /* add a name to an existing pointer - va_list version -- cgit