Re: [gtk-list] Re: Tracking object deletion



On 11 Dec 1997, Owen Taylor wrote:

> But I still think that [keeping a refererence count, and making Gtk
> functions fail silently] better [than the deletion callback]- when
> combined with a way for users to check if GdkWindow/Pixmap is still
> valid or not. It is the way you want to handle most objects - if the
> user keeps around a reference in Perl to an object, it shouldn't be
> destroyed, IMO. And thus its probably better to handle objects that are
> destroyable by outside-forces in the same manner. 

My thought is something in between: reference counting is good, because it
lets both Gtk and external language keep hold of an object (so that if I
say:

  $b = new Gtk::Button "Add sheep";

then $b will still around no matter what I do to it, or where I add or
remove it from, until $b itself is cleared) but when it conflicts with the
window management, everything goes haywire.

The other token is that a deletion callback turns out to be _critical_,
for reasons I had completely missed. Consider creating a new Gtk widget in
Perl, called GtkFoo, that is descended from GtkButton:

  package Gtk::Foo;

  use Gtk;

  @ISA=qw(Gtk::Button);

  register_type Gtk::Foo;

  sub new { Gtk::Object::new(@_) }
  sub class_init {}
  sub init {}

(Before you ask, yes that is legal & functional code in the version I'm
working on.) 

Once I say:

  $x = new Gtk::Foo "GtkButton::label" => "Add goat";

I've got a Perl object, called a "shadow object", that allows Perl to
invoke Gtk functions, and also can store arbitrary data that is
effectively connected with the Gtk object (it's even available from C
programs, if you really wanted it.). If I then say: 

  $x->{arbitraryData} = 3;
  $window->add($x);
  $x = unref;
  $y = $window->children[0];
  print $y->{arbitraryData};

then $y must contain the same Perl object refernce as $x did. (In the
current release, $y is constructed anew, and {arbitraryData} will not be
present). For this to work, we've got two options:

  1) the new Gtk object type must contain a reference to the Perl object,
     so that when we reconstitute $y from the pointer that
     gtk_container_children() gave us, we simply use the stored reference.
     However, this means we've got a reference loop, as the Perl object
     refers to the Gtk object, and vice versa. Now reference counting is
     worthless again, unless we go back to manual destruction functions,
     weak references, extremely dangerous coding, or don't let the Perl
     object refer to the Gtk object (which means all Perl calls must
     verify a valid reference count).

  2) create the Perl shadow object the first time the Gtk pointer is seen,
     and install a hook to catch deletion of that object. The Perl object
     holds a reference to the Gtk object, but not vice versa. If the Perl
     object is deleted, the Gtk object stays around (unless its references
     run out) and if Perl gets hold of it again, the same shadow object
     will be used (via a hash that does not hold true references, just
     pointers). The shadow object is only deleted when the
     destruction callback is invoked and, by definition, the Perl
     shadow object will already have been deleted.

#2 seems far safer and maintainable. Some sort of weak references are
probably feasible, but mean much more coding all around.

In any case, I still very much would like to see reference counting, but
_not_ mixed up with the window management. A container should certainly
keep references to its children, and letting objects destroy themselves if
their container is destroyed makes good garbage collection sense. But the
window manager "close window" function should _not_ trigger an unref(), as
that means programs now have to actually catch unref() and then undo it,
if they want to stick around for a while. 

Probably the simplest approach would be to have a "wm_close" signal that,
by default, is set to widget_unref(). If a programmer wants to trap the
close event on a window, they merely replaces the "wm_close" signal, and
issue hide(), unref(), or something else entirely, as they desires.

I think I can sum my thoughts up this way: 

 1) make an "object deletion" hook, something a bit lower down then a
    signal, that serves only to tell programs that an object is being
    destroyed. This hook _must_ be called after every other conceivable
    signal/hook that might want to do something constructive [sic] with
    the object. 

 2) every single set of ref/unref calls should be rewritten to meet the
    usual definition: no externally accessible destroy() call, and when
    unref() removes the last reference, the object is automatically
    destroy()'d. This is probably going to be an absolute pain for some of
    the GdkColor stuff, BTW. 

 3) any operations that the programmer might want to catch (WM_CLOSE,
    etc.) should not call unref() directly, but should call a signal that
    in turn calls unref() by default.

> These issues come up with a vengeance when dealing with networked
> objects. Substitute:
> 
>   X window => remote object
>   GdkWindow => locale surrogate object
>   Perl refernce to such => language specific reference to remote object
> 
> Normally CORBA doesn't keep a reference count so local surrogates may
> become invalid. (But CORBA does have EH - which is a slight help) ILU
> allows keeping of reference counts as an extension, which is handy for
> many things (DCOM is similar, I think). But for networked objects, you
> need a keep-alive callback for the clients holding reference counts,
> since otherwise if the remote client dies silently, objects will never
> be destroyed.

I think this could work either way. A reference count can _always_ be
implemented (unless CORBA truly assumes that programs delete random
objects for no apparent reason at random times. And the keep-alive that
destroys the objects when the link is dead can easily trigger a
destruction event while it is at it.

> Wow, I really strayed off track. I guess the short answer is - for
> now, use "destroy" and warn users off referring to the object in an
> installed "destroy" handler. In the future, you probably shouldn't
> have such a thing.

I really hope we have something just as useful then.

For example, I just realized that gtk_object_set_data() could work in
exactly the manner I need, _if_ there was a callback that could be invoked
when the data was cleared, due to object destruction. The most basic point
is I need _some_ way to tell all Gtk objects, even ones not descended from
a Perl class, that they need to tell Perl about their disappearence.

> 
> Regards,
>                                         Owen
> 
> P.S.
> 
> While I'm on the subject, I'll bring up a related issue:
> 
> When should Marius's patches go in? (See his post a few weeks ago for
> more details) It will break most existing apps in a few easy-to-fix
> ways, and possibly in more subtle ways if they tried to do
> sophisticated things. (But if they did so, they are probably broken,
> since GTK can't do those sophisticated things now).

On that, I cannot comment. I am working on this module in what amounts to
my spare time, and am using a hardwired (as well as mutilated and
extended) version of gtk.defs that I borrowed from some or other version
of Gtk. As Gtk (and gtk.defs) improves, I'll shift the Perl code over. 

> The looming specter is the release of the GIMP. It's probably better
> to make the changes now, while the GIMP is (barely) prelease, then
> break compatibility later. But the opposing view is: "things almost
> work now for the GIMP, wait until later, to do things that might
> introduce bugs"

Some parts of Gtk need an overhaul, unquestionably. (By far the largest
part does not. I am utterly astonished how easy it was to glue Perl in,
and it gets easier every version.) However, the visible changes should be
minor, unless Gtk (and attendant plug-ins) are strongly abusing the
reference system.

I think you should try to avoid having Gtk 1.0 (used by GIMP) and Gtk 2.0
(which has all the new features, but GIMP doesn't understand). This is the
sort of thing which gives Tcl/Tk users fits. How that can be arranged, I'm
not sure. 

Cheers,
Ken
-- 
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)




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