Re: [gtk-list] Looking for info on gtk_widget_unref semantics.



On 16 Aug 1999, Rob Browning wrote:

> 
> As an example, if I create a widget, but then never use it (because
> something else failed) do I need to unref it?  How about if I create a
> widget, then put it in a vbox, do I need to unref it? etc.

the first issue is actually a tricky one because toplevels behave different
from the rest of the objects here, they need to be explicitely destroyed.

so you'd actually do:

widget = gtk_widget_new (GTK_TYPE_WIDNOW, NULL);
gtk_widget_destroy (widget);

for windows, and:

widget = gtk_widget_new (GTK_TYPE_VBOX /* or any other non-window type */, NULL);
gtk_widget_unref (widget);

for other widget types, but you usally don't have to deal with this, since
you normaly simply add children to containers and the containers care about
destruction of their children.
so the only thing that you usually have to care about is destroying all
your toplevels.


there are only two typical circumstances where you need to care about
refcounting at all, the first is reparentation. when you initially add
a widget to a container, the container takes over its initial reference
count, and that is dropped when the widget is removed from the container
and then the widget is automatically destroyed. when reparenting widgets,
you want to avoid that, so you do:

/* "container1" has a child "widget" that we want to move to "container2" */
gtk_widget_ref (widget);
gtk_container_remove (container1, widget);
gtk_container_add (container2, widget);
gtk_widget_unref (widget);

the second case is when you are keeping a reference to a widget, e.g. a
label that you want to frequently update. lets say you put the label's
pointer into a static variable to easily update its contents from a
public function:

static GtkWidget *my_status_label = NULL;

void
my_status_change (const gchar *status)
{
  gtk_label_set_text (GTK_LABEL (my_status_label), status);
}

you've got two choices here: either you keep an extra reference count on
the label that assures that the label stays alive, so you don't reference
invalid memory from my_status_change() after the label got destroyed, or you
use destroy notification, so you can reset your pointers.
keeping a reference count might look like so:

static GtkWidget *my_status_label = NULL;

void
my_status_set_label (GtkLabel *label)
{
  if (my_status_label)
    gtk_widget_unref (my_status_label);
  my_status_label = label;
  if (my_status_label)
    gtk_widget_ref (my_status_label);
}

void
my_status_change (const gchar *status)
{
  if (!GTK_OBJECT_DESTROYED)
    gtk_label_set_text (GTK_LABEL (my_status_label), status);
}

you then have to asure that you call my_status_set_label (some_label) before
you use my_status_change()) and call it as my_status_set_label (NULL) when
you don't need to display status info anymore, and don't want to leak
memory.
using destroy notification, you'd do something like this:

static GtkWidget *my_status_label = NULL;

static void
reset_status_label (void)
{
  my_status_label = NULL;
}

void
my_status_set_label (GtkLabel *label)
{
  if (my_status_label)
    gtk_signal_disconnect_by_func (GTK_OBJECT (label), reset_status_label, NULL);
  my_status_label = label;
  if (my_status_label)
    gtk_signal_connect (GTK_OBJECT (label),
                        "destroy",
                        reset_status_label,
                        NULL);
}

void
my_status_change (const gchar *status)
{
  if (my_status_label)
    gtk_label_set_text (GTK_LABEL (my_status_label), status);
}

which one you choose for your actuall implementation heavily relies on
the specific situation, but in general destroy notification is the
better aproach, as it keeps your internal data accurate.

as a special remark, code that uses destroy notification *and* explicit
reference counts is usually broken and indicates that the author either
didn't know what to choose or wasn't quite aware of the usefulness/
implications of either mechanism.


however, back to your question on creating a widget that gets never used,
there is actually a way to destroy all kinds of objects, which is:

object = gtk_object_new (GTK_TYPE_<somthing>, NULL);

gtk_object_ref (object);
gtk_object_sink (object);
gtk_object_destroy (object);
gtk_object_unref (object);

but this is really getting into the deeper magic of the refcounting system,
especially with regards to "sinking" an object. gtk+/docs/refcounting.txt
covers this in more detailed fashion, and as stated above, you usually
do not need to care about that.


> 
> Thanks
> 

---
ciaoTJ



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