Hi John,

On 05.10.2010, at 22:07, John Obbele wrote:

> Good evening !
>
> On Mon, Oct 04, 2010 at 09:53:56AM +0200, Axel Simon wrote:
>>
>> On Oct 3, 2010, at 22:42, John Obbele wrote:
>>> Optimally, I would wish to provide a dummy memory finalizer to
>>> the gtk2hs GObject implementation but it seems this can't be
>>> easily done (for good reasons I assume).
>>>
>>
>> The good reason is that XfconfChannel may cease to exist before the
>> Haskell object goes out of scope (well, at least in principle this
>> is a possibility). If you don't use constructNewGObject, then
>> Haskell land may refer to a destroyed C structure.
>
> That's sound right to me.
>
> Note also that in the previous case, construct/makeNewGObject
> works equally well, my bad for not understanding this before but
> XfconfChannels are NOT floating objects.
>
>>> 2) xfconf_channel_new returns a newly created clone. You need to
>>> call object_unref to free it but neither object_ref nor
>>> object_ref_sink. Problem: makeNewGObject calls the former and
>>> constructNewGObject the latter.
>>>
>>> Simple solution : call directly the C functions like this:
>>>
>>>      channelNew :: String -> IO XfconfChannel
>>>      channelNew name =
>>>          withUTFString name $ \cname -> do
>>>              objPtr <- {#call xfconf_channel_new #} cname
>>>              obj <- newForeignPtr objectUnref objPtr
>>>              return $! XfconfChannel obj
>>>
>>>
>> I consider this behaviour as broken. I think object_ref_sink should
>> do the right job for exactly this problem. If it doesn't then our
>> other code might be broken (or XFconf is simply not adapted to the
>> new sink/ref mechanism, although I thought it should be backwards
>> compatible).
>
> I don't think this is broken. I'm not a glib expert/developer so I
> might be wrong but after re-reading the brief GObject stuff about
> floating references [0], I understand the situation this way:
>
> [0]: 
> http://library.gnome.org/devel/gobject/stable/gobject-The-Base-Object-Type.html#gobject-The-Base-Object-Type.description
>
> /me puts its "cap'tain obvious" hat, sorry if I repeat things  
> everybody
>    already knows
>
> 0) Floating references are just syntactic sugar for lazy C  
> programmers.
>   The idea is simple: when dealing with widgets, 99% of the time, you
>   add them to containers and they belong to the *container*, not your
>   `create_ui` function. So in order to avoid thousands of
>   `gtk_container_add (box,widget) && g_object_unref (widget)`, glib
>   developers have created floating references:
>
>    GtkWidget* create_ui(void) {
>        GtkWidget *box = gtk_hbox_new( ...);      // box->ref_count = 1
>        GtkWidget *button = gtk_button_new( ...); // button- 
> >ref_count = 1
>
>        /* At this point, both box and button are "owned" by createUI  
> */
>
>        gtk_container_add (box, button);          // button- 
> >ref_count *STILL* = 1
>        /* g_object_unref (button); */            /* unneeded */
>
>        /* Now, (*button).ref_count, originally owned by "createUI",
>         * was overwritten (sunk ?) by `gtk_container_add`.
>         *
>         * If you delete (*box), it will break its reference to  
> (*button)
>         * and thus destroy it. Hence (*button) effectively "belongs  
> to"
>         * (*box).
>         */
>
>        return GTK_WIDGET (box);
>    }
>
> 1) XfconfChannel are not widgets. You do not store them in boxes,  
> You do
>   not "transfer their ownership to the first container passing by".
>   Consequently they do not need floating references and the ref_sink
>   mechanism.
>
>   A simple Haskell function should looks like this:
>
>    readMyConfiguration :: IO Configuration
>    readMyConfiguration = do
>        chan <- channelNew "Foobar"
>
>        option1 <- channelGetProperty chan "foo1"
>        option2 <- channelGetProperty chan "foo2"
>
>        return (Configuration option1 option2)
>
>        -- Note that the last `g_object_unref` is omitted in Haskell
>        -- because this is why the GC is here for. "chan" is
>        -- automagically clean thanks to its finalizer.
>
>   If I had defined "channelNew = makeNewGObject (...) {#call  
> channel_new#}",
>   `{#channel_new#}` would return a non-floating object with  
> ref_count = 1,
>   makeNewGObject would increase the reference to 2 and finally the
>   Haskell GC would finalize my channel and decrease its ref_count back
>   to 1.
>
>   If I had defined "channelNew = constructNewGObject (...) {#call  
> channel_new#}",
>   this would be exactly the same problem, since `constructNewGObject`
>   would call `g_object_ref_sink` which equals `g_object_ref` for non- 
> floating
>   objects.
>
>   In both case, at the end of "readMyConfiguration", chan->ref_count  
> == 1.
>   The object is not destroyed by Glib. I have a memory leak.
>
>   /me puts its "engineer" hat
>
>   And I am fairly confident about this fact. I've used
>
>    testLoop :: IO ()
>    testLoop = replicateM_ 100000 (channelNew "foo" >>=  
> channelOperation >>= print)
>
>   … and experimental results show that the only way not to get a  
> memory
>   leak, is to by-pass both constructNewGObject and makeNewGObject.
>
> /me puts its "naïve computer scientist" hat.
>
> 2) Note that all this discussion is only relevant to non-floating
>   objects.
>
>   I've rewrite the first C example and loop over creating widgets /
>   unreferencing them, just to be sure, and the gtk2hs program shows no
>   memory leaks.
>
>
> Conclusion:
>
> 1) constructNewGObject/makeNewGObject cannot be used in gtk2hs for new
>   *non-floating* GObjects, that is for every object not inheriting
>   from "GInitiallyUnowned".
>

Thanks for your observations and musings. We did have a report on an  
apparent memory leak in Pixbuf, which is indeed not a Widget.

I assumed that the floating concept is applied to any GObject. Since I  
seem to be wrong about this, we have to revise quite a few things in  
Gtk2Hs. So we need a new function that does not increase the refcount.  
wrapGObject perhaps?

> 2) I will hang myself if I have to test anymore ref_counts in gtk2hs.
>

Too bad. I would have set you up scurrying the land of Pixbufs and  
their references. Alas, I have to do that myself.

> please beat me ,)

Unless you beat me to it.

Axel

> /John
>
> ------------------------------------------------------------------------------
> Beautiful is writing same markup. Internet Explorer 9 supports
> standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
> Spend less time writing and  rewriting code and more time creating  
> great
> experiences on the web. Be a part of the beta today.
> http://p.sf.net/sfu/beautyoftheweb
> _______________________________________________
> Gtk2hs-devel mailing list
> Gtk2hs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel


------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today.
http://p.sf.net/sfu/beautyoftheweb
_______________________________________________
Gtk2hs-devel mailing list
Gtk2hs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel

Reply via email to