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