Re: Glib ref-counting question



I do not know the answer to your question but I thought I would investigate a 
little.

I guessed that the input functions described in Havoc Pennington's book 
GTK+/Gnome Application Development were probably implemented using the same 
functions g_io_channel_* that you are using. I looked at the code in the 
directory gtk+/gdk.

In gdkevents.c I found gdk_input_add_full(). This function is similar to your 
foo_open() in that it calls g_io_channel_unix_new() and g_io_add_watch_full(). 
It then calls g_io_channel_unref(). This looks similar to object sinking in 
GTK+.

If you do something similar you should get the ref count to zero.

Padraig


> Delivered-To: gtk-list gnome org
> Subject: Glib ref-counting question
> To: gtk-list gnome org, gnome-devel-list gnome org
> Mime-Version: 1.0
> X-BeenThere: gtk-list gnome org
> X-Loop: gtk-list gnome org
> X-Mailman-Version: 2.0beta5
> List-Id: General discussion of GTK+ <gtk-list.gnome.org>
> 
> Hi, I have a programming strategy question. Consider the following code
> bite which represents something that I have:
> 
> /*************************************/
> 
> struct Foo {
>         GIOChannel iochannel
>         // others
> }
> 
> Foo*
> foo_new(int id)
> {
>         Foo* foo = g_new0(Foo, 1);
>         // stuff
>         return foo;
> }
> 
> gboolean
> foo_open(int id)
> {
>         foo->iochannel = g_io_channel_unix_new(id);   // L1
>         g_io_add_watch(foo->iochannel, G_IO_IN, G_IO_FUNC(foo_read),
> foo);   // L2
>         g_io_add_watch(foo->iochannel, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
> G_IO_FUNC(foo_error), foo);   // L3
> }
> 
> void
> foo_close(Foo* foo)
> {
>         g_io_channel_close(foo->iochannel);   // L4
>         foo->iochannel = NULL;
> }
> 
> gboolean
> foo_read(GIOChannel* iochannel, GIOCondition cond, Foo* foo)
> {
>         GIOError error = g_io_channel_read( ... );
>         if (error == G_IO_ERROR_NONE || G_IO_ERROR_AGAIN) {
>                 // stuff
>                 return TRUE;
>         } else {
>                 foo_close(foo); // L5
>                 return FALSE;  // L6
> 
> gboolean
> foo_error(GIOChannel* iochannel, GIOCondition cond, Foo* foo)
> {
>         // stuff
>         foo_close(foo);  // L7
>         return FALSE;   // L8
> }
> 
> /*************************************/
> 
> The problem is that the iochannel is not not freed when foo_close() is
> called. Because the g_io_channel_close does just one g_io_channel_unref,
> but the ref-count is 3, so it goes down to only 2 (or 1 if foo_close()
> is called from foo_read() or foo_error() becase they return FALSE, hence
> removing the watch and thus unreffing one more time).
> 
> What should I do to ensure the iochannel is freed in foo_close()? Should
> I put this after L4:
> 
> g_source_remove_by_user_data(foo);
> 
> But that only unrefs once, and the refcount might still be > 0. And the
> ref count is a private field. So what should I do?
> 
> Thanx in advance for any help.
> 
> /-------------------------------------------------------------------\
> |   LOBAN AMAAN RAHMAN  <-- anagram of -->  AHA! AN ABNORMAL MAN!   |
> |     loban earthling net, loban caltech edu, http://i.am/loban     |
> \-------------------------------------------------------------------/
> 
> _______________________________________________
> gtk-list mailing list
> gtk-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-list





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