Re: gtk2-perl / a script to help converting basic functions



I find all thoses problems stranges. For me, when a user create a Gtk
object, he must destroy it. When object is packed into another object
you only have to destroy the root object. So the Gtk way of doing things
is sufficent.

The Perl problem is with the Perl structure which keep the C pointer.
This perl structure must use the Perl garbage collector without having
to care about the C pointer because if the user lose the reference to
this pointer it just means he will only access it with a root parent (I
think).

The problem for string is to copy the string in the Perl way of keeping
string. Perl will free the string like for any string in "normal" Perl.
The original returned pointer to the string by the C function is just
freed. I don't know enough about Perl internal to know if it is so easy
but it is the way we should follow.

For object like GdkDrawable (is it very rare that those object are only
that type) most often we create them to give them to some kind of widget
and they are freed when the widget is freed (we have to verify that).

If you create such an object and don't use it for a widget then you have
to use the unref funtion of all GObject.

But using a DESTROY with unref on it is dangereous because those object
can be use by other part of Gtk while no more accessible by Perl.

Daniel Lacroix

Le ven 25/10/2002 à 15:08, Guillaume Cottenceau a écrit :
goran kirra net writes:

we can not free memory we have passed to libgtk+ so
generic DESTROYs aren't working. There are "ref count"
variables in some struct that can be usable
We should be more careful about freeing memory
but I think it requires an inteligent decision
in every case individually.

I've been working on that topic since yesterday, with even some
kind help from Sven Neumann[1], and I'd like to show my code
proposal so far.


One has to know that there are 3 classes of objects to
distinguish:

- the GtkObject hierarchy
- the GObject hierarchy that don't inherit from GtkObject as well
- structs (things such as GdkColor, GtkTextIter, etc)


In the GtkObject hierarchy, objects that are not toplevel widgets
are created in the "floating" state. It means that they don't
have yet a parent. Then when they are associated with another
object (box_pack and container_add), this floating state
disappears. The nice thing is that when the "top" parent gets
destroyed (the GtkWindow) it will free up the associated memory
of its whole child tree.

So basically for that hierarchy, we:

- explicitely gtk_widget_destroy when a Gtk2::Window gets
  DESTROY'ed

- could explicitely gtk_object_sink all widgets that are still in
  the "floating" state, but this would require tricky
  operations[2], so I suggest to ignore them (there won't be much
  harm to leak memory of objects the user creates without using
  them, because no one wants to do that in the long term)


In the GObject hierarchy, objects use the normal refcounting
strategy, (without the "floating" state). The problem is that
some GObject are given back to the user already owned by another
widget (for example Gtk2::TextView::get_buffer) while some not
(for example Gtk2::Style::new), and Sven confirmed that there is
no function/macro to query a GObject for that property. So we
have two solutions here:

1. do it for the user - but then we need to split up the perl
   object creators by hand, to remember that some objects are
   only references to existing objects that won't need to be
   freed up, and some others not;

2. let the user do it - that means, when she creates a
   Gtk2::Style, she needs to $style->unref() it before it's
   destroyed, if she wants to not leak memory;

The -2- is my preferred solution, since -1- needs that we do
extra care to call the right perl object creator if we don't want
to segfault (if we unref a buffer returned by get_buffer, the
program will segfault when the textview gets destroyed).

The bad side of -2- is that it's not consistent with what we do
in the GtkObject hierarchy; e.g. there is implicit calling
of gtk_widget_destroy in the DESTROY of Gtk2::Window, but
explicit unref for GObject's.

I have implemented the necessary code for -1-, though.


As for structs, we explicitely g_malloc the associated memory
(GdkColor etc), so the easy solution is that all the perl object
wrappers for structs inherit from Gtk2::Struct in which we put a
DESTROY that explicitely g_free the associated memory.


Please find attached the code proposal (the GdkWindow also needs
to be explicitely destroyed, this time with gdk_window_destroy):

----




My tests show that it allows the following code block to not leak
memory at all:

{
    my $textview = Gtk2::TextView->new();
    my $wrapmode = $textview->get_wrap_mode();
    my $buffer = $textview->get_buffer();
    my $bounds = $buffer->get_bounds();

    my $button = Gtk2::Button->new_with_label('hello!');
    my $vbox = Gtk2::VBox->new(0, 0);
    $vbox->pack_start(Gtk2::ProgressBar->new(), 0, 0, 0);
    $vbox->pack_start($button, 0, 0, 0);
    $vbox->pack_start($textview, 0, 0, 0);

    my $window = Gtk2::Window->new('toplevel');
    $window->add($vbox);

    my $style = Gtk2::Style->new();
    $style->unref();

    my $color = Gtk2::Gdk::Color->new(150*256, 250*256, 0);
    my $color2 = Gtk2::Gdk::Color->parse('blue');
}


Please tell me if it's ok for you, then I'd commit.

Thanks,


Ref: 
[1] reading docs/refcounting.txt from the gtk+ sources helped a
    lot

[2] in a perl block, you create a GtkWindow and add it a
    GtkFrame; when the perl destructors are called, you don't
    know in which order they will be; if the perl destructor of
    the window is called first, it calls gtk_widget_destroy, and
    gtk also destroys the add'ed frame; then when the perl
    destructor of the frame gets called, you can't even test to
    see if it's a floating object since it has already been freed
    up when the window has been destroyed (testing gives a glib
    warning log); so to implement that, we'd require much trick
    which are not worth the worry IMHO (the trick could be to add
    code when we container_add and box_pack to flag the
    associated widgets for being ignored when later destroyed,
    for example)

-- 
Guillaume Cottenceau - http://people.mandrakesoft.com/~gc/





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