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



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):

Attachment: jkiu
Description: Binary data



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]