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
> [email protected]
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel