[QUICK] talloc bugs
Rusty Russell
rusty at rustcorp.com.au
Wed Jul 1 12:24:24 GMT 2009
On Wed, 1 Jul 2009 09:28:32 pm simo wrote:
> On Wed, 2009-07-01 at 21:20 +0930, Rusty Russell wrote:
> > I don't think references are a fundamental part of talloc: they are
> > useful, and I think helpers to allow them could be great, but I'd rather
> > see some explicit demarcation of what is reference counted. See followup
> > code.
>
> Another way could be to attach some code like we do with
> talloc_destructor(), with the ability to tell the calling talloc code to
> reparent instead of free.
This would work, and doesn't even need to be inside talloc (tho if you want to
support talloc_realloc it should be: references currently don't allow that).
Cheers,
Rusty.
#ifndef TALLOC_LINK_H
#define TALLOC_LINK_H
/* Add a link between a context and another talloc object. This
* implicitly does a steal of the linked object to become a descendent
* of ctx.
*
* You can do any number of talloc_link() calls to a linked object.
* talloc_steal or talloc_free of the linked object breaks the links
* (you probably don't want to do this). Otherwise, freeing the last
* talloc_linked ctx frees linked.
*/
int talloc_link(const void *ctx, const void *linked);
/* Explicitly remove a link: normally it is implied by freeing the
* ctx. ctx must have been linked to the object using talloc_link.
* Removing the last link frees the object. */
void talloc_delink(const void *ctx, const void *linked);
#endif /* TALLOC_LINK_H */
#include <ccan/talloc/talloc.h>
#include <ccan/talloc_link/talloc_link.h>
struct talloc_link {
struct talloc_link *next, *prev;
const void *obj;
};
static int destroy_link(struct talloc_link *link)
{
/* Try to hand off parentage to another link. */
if (talloc_is_parent(link, link->obj))
talloc_steal(link->next, link->obj);
/* Unlink ourselves */
link->next->prev = link->prev;
link->prev->next = link->next;
return 0;
}
int talloc_link(const void *ctx, const void *linked)
{
struct talloc_link *link, *oldlink;
link = talloc(ctx, struct talloc_link);
if (!link)
return -1;
talloc_set_destructor(link, destroy_link);
/* Already linked? */
oldlink = talloc_get_type(talloc_parent(linked), struct talloc_link);
if (oldlink) {
link->next = oldlink;
link->prev = oldlink->prev;
oldlink->prev = link;
link->prev->next = link;
} else {
link->next = link->prev = link;
}
link->obj = talloc_steal(link, linked);
return 0;
}
void talloc_delink(const void *ctx, const void *linked)
{
struct link *link, *i;
link = talloc_get_type(talloc_parent(linked), struct talloc_link);
/* Talloc steal could have taken us away. */
if (!link)
return;
i = link;
do {
if (talloc_is_parent(ctx, i)) {
talloc_free(i);
return;
}
i = i->next;
} while (i != link);
/* Talloc steal then linked to by other links? */
}
More information about the samba-technical
mailing list