[QUICK] talloc bugs

Sam Liddicott sam at liddicott.com
Wed Jul 1 09:47:59 GMT 2009


* ronnie sahlberg wrote, On 01/07/09 10:05:
> For talloc becoming a standalone library,
> do you think it would be useful if I port the red-black talloc tree
> from ctdb as a patch to talloc?
>
> In CTDB we have an implementation for red-black trees that is adapted to talloc.
> It has nice features such as the nodes in the tree are child objects
> not to the tree itself but the data that is referenced in the tree.
> For example, if you store an object in one or more trees and later
> talloc_free() that object, the object is automatically demoved from
> all the tree's as well.
>   

This seems a very nice use of talloc.

I can also think of cases where presence in the tree might also be
intended to prevent the data from being destroyed. I suppose that in
these cases the tree would also talloc_reference the data; and so there
exists a concept of the tree having a strong or weak reference to the
data within it.  I like the way you have this arranged so that when all
strong references are gone, the weak references are used to remove the
item from the true.

Today I just learned that when a gtk widget is destroyed it sends a
signal to all those things that hold a reference and tells them to let
it go.

This is precisely what you do; and so I see that with talloc, to hold a
weak reference to an object means that the object actually has the
reference to you (or to some handle).

The validity of the weak reference can be tested by checking if the
objects reference has gone away - either by a destructor callback or by
counting the number of references remaining.

A full implementation would have a pair of references. One entirely
owned by the object against which the weak reference is held, whose
destructor will notify the other reference which is not destroyed. This
other reference is owned by the object holding the weak reference,
which, when destroyed will remove it's twin from the object being
referenced. Otherwise when the referencing parent die, the reference
would remain until the referenced object died.

struct talloc_weak_reference {
  void* referenced;
  struct talloc_weak_reference* twin;
}

struct talloc_weak_reference* make_weak_reference(void* mem_ctx, void*
ptr) {
  struct talloc_weak_reference* ref = NULL;
  struct talloc_weak_reference* ref_handle = NULL;

  if (! ptr) return NULL;

  /* We don't talloc ref against the item to be referenced in case it
has a talloc pool in whose centre we might remain */
  ref = talloc_new(NULL, struct talloc_weak_reference);
  if (! ref) goto error;

  ref_handle = talloc_new(mem_ctx, struct talloc_weak_reference);
  if (! ref_handle)  goto error;
  ref_handle->referenced = ptr;

  ref->referenced=talloc_steal(ref, ptr);
  if (! ref->referenced) goto error;
  ref->twin = ref_handle;
  talloc_set_destructor(ref, talloc_weak_ref_destructor);

  ref_handle->twin = ref;
  talloc_set_destructor(ref_handle, talloc_weak_ref_handle_destructor);

  return ref_handle;

error:
  if (ref) talloc_free(ref);
  if (ref_handle) talloc_free(ref_handle);
  return NULL;
}

/* the tracked object has gone away, tell the weak ref handle */
int talloc_weak_ref_destructor(struct talloc_weak_reference* ref) {
  if (ref->twin) {
    ref->twin->referenced = NULL;
    ref->twin->twin=NULL;
    ref->twin=NULL;
  }
}

/* we don't want the weak ref any more */
int talloc_weak_ref_handle_destructor(struct talloc_weak_reference*
ref_handle) {
  struct talloc_weak_reference* ref = ref_handle->twin;
  if (! ref) return 0;

  /* detach us from the weak reference prior to calling it's destructor */
  ref->twin = NULL;
  /* remove it from being referenced by that which it tracks, probably
also destroying it */
  talloc_unreference(ref->referenced, ref);
  /* remove our link to it */
  ref_handle->twin=NULL;
  ref_handle->referenced=NULL;

  return 0;
}

Sam


More information about the samba-technical mailing list