g_source_unref() and g_source_destroy() are your friends

After almost 2 years developing GLib-based applications, I understood the proper way of using GSource objects. Yes, quite a shame, but better now than never.

Now, after re-reading carefully the GLib Reference Manual, I see that it is quite clearly explained the difference between g_source_destroy() and g_source_unref(). So the typical suggestion is still the best one: RTFM!!

In our applications, we usually need to attach timeout operations to the context of an specific thread, not to the main thread context. Thus, we cannot use g_timeout_add() or the pretty new g_timeout_add_seconds().

For example, you could create a GThreadPool, and in the function to be executed in each thread, you could create a specific context for the thread, plus a main loop in the context:

    /* Create a GLib Main Context */
    context = g_main_context_new();

    /* Create a Main Loop in the context*/
    main_loop = g_main_loop_new(context,
                                FALSE);

Once you have a new context and main loop, you can just create a new GSource, and attach it to the main loop. As soon as you create the GSource, its reference count is 1, and as soon as you attach it to the main loop, its reference count will be 2.

    /* Create new timeout source to be called
     * every 5 seconds.
     * Reference count of source is 1 once created */
    source = g_timeout_source_new(TIMEOUT_MSECS);

    /* Set callback to be called in each timeout */
    g_source_set_callback(source,
                          (GSourceFunc)__timeout_func,
                          main_loop,
                          NULL);

    /* Attach the GSource in the GMainContext.
     * Reference count of source is 2 after this call */
    g_source_attach(source,
                    context);

Of, course, you will be now running the main loop:

    /* Run the main loop, until it is stopped */
    g_main_loop_run(main_loop);

The key now is how to destroy the GSource properly. When calling g_source_destroy(), you are doing 2 things: first, telling the main loop to forget about the GSource; and second, decrementing the reference count of the GSource. Then, you still need to call g_source_unref() to fully decrement the reference counter so that the GSource is disposed.

    /* We did an attach() with the GSource, so we need to
     * destroy() it */
    g_source_destroy(source);

    /* We need to unref() the GSource to end the last reference
     * we got */
    g_source_unref(source);

To end the example, once the main loop is stopped, you will also need to properly dispose the GMainContext and GMainLoop objects:

    /* The main loop should be destroyed before the context */
    g_main_loop_unref(main_loop);

    /* Finally, destroy the context */
    g_main_context_unref(context);

This is just one way of keeping the GSource references properly managed:

  1. You get one reference when you create the GSource
  2. You get a new reference when you attach it in the context
  3. You release one reference when you destroy it from the context
  4. You release last reference when you unref the final one

Of course, you could also choose to avoid storing the “extra” reference, and leave alive only the one inside the main context:

  1. You get one reference when you create the GSource
  2. You get a new reference when you attach it in the context
  3. You release one reference when you unref the the GSource —> Now, the only reference is inside the GMainContext
  4. You release last reference when you destroy it from the context

You can check this simple example in the following program I prepared, released into public domain:
http://es.gnu.org/~aleksander/glib/test-gsource.c

Hope it helps someone out there to fully understand the difference between g_source_destroy() and g_source_unref().

As last comment… I would really rename the following functions in the library, so that no one else is confused with the “unref” and “destroy” terms:

  • Rename g_source_attach() to g_source_attach_to_context()
  • Rename g_source_destroy() to g_source_destroy_from_context()

The main reason is that these two operations actually act on the GMainContext, while the name of the functions do not suggest that fact.

Posted on January 5, 2010, in Development and tagged , . Bookmark the permalink. 5 Comments.

  1. Thanks for this wonderful blog. I am in process of development of a stack using glib. Hope I get help from you.

  2. Agree. Very useful as this issue was a bit unclear.

  3. This destroys and unref a gSource only when the main loop quits…. In case the main loop is long running, how to handle the freeing of gSources?

  4. If you no longer need the GSource, just call g_source_destroy(source); while the main loop is running, that will detach it from the main loop. Still, if you had an additional reference not yet released (the one you got when creating the GSource and before attaching it), just add the additional unref().

    A good compromise for this case is to create the GSource, attach() it to the main loop and directly release a reference with unref(). In this case, the one and only reference left will be the one kept due to the attachment to the main loop (i.e. the GSource is now owned by the loop itself), so that whenever you destroy() the reference (to detach it) or when the GMainLoop itself is fully disposed, the GSource will get also fully disposed.

  5. Gaurav Kalra

    Thanks.
    That made my doubt clear🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: