Re: weakened userdata




On Dec 29, 2007, at 7:34 PM, Kevin Ryde wrote:

When making a signal callback in a child widget to act on some parent,
with the parent as the userdata in the signal, is there a usual way to
weaken or do something to that userdata to avoid creating a circular
reference?

This issue exists with all signal connections in gtk2-perl. It's a little more subtle when dealing with closures, where it's easy to trap a self-reference by accident.

The way that GObjects destroy themselves mitigates the reference cycle problems for the most part. In the process of destruction, the signal closures get destroyed, which causes the reference count on the user- data scalar to drop. So,


    $a is some object with reference count a'
    $b is some other object with reference count b'

    $id = $a->signal_connect (frob => \&frob, $b);
    $a still has refcount a'
    $b now has refcount b'+1

    $a->signal_handler_disconnect ($id)
    $a still has refcount a'
    $b now has refcount b' again


The equivalent of signal_handler_disconnect() happens as part of the "dispose" stage of GObject destruction.

The case where you can get hosed is

      $a->signal_connect (frob => sub { $a->blurp () });  # BAD!

because the closure now keeps a reference to $a that can't be killed until you disconnect the signal; if you didn't trap the id to disconnect that signal directly, then you have a memory leak. It's better to structure such things like this:

      $a->signal_connect (frob => sub { $_[0]->blurp () });

or

$a ->signal_connect (frob => sub { my $a = shift; $a->blurp (); });

to avoid capturing that reference to $a in the closure.


If you have something you can't get rid of normally with a Gtk2::Object, you can connect to the "destroy" signal and break the reference cycle there. However, i've found it very rare to need to do this, so i can't really think of any good examples.


--
The one difference between Dali and a crazy man is very simple: Dali is not crazy at all.
  -- Salvador Dali





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]