g_timeout_add inside a GThread
Asked Answered
T

1

3

I'm trying to add a timeout source specific to a particular GThread.

In the main thread, I can create a GMainContext (g_main_context_new) and add a timeout (g_timeout_add). However, when I try to do it in a thread created with g_thread_create it simply doesn't work, the GSourceFunc is never called and I have no clue why.

For the moment I've only got this the documentation:

Callbacks require a bit of attention. Callbacks from GTK+ (signals) are made within the GTK+ lock. However callbacks from GLib (timeouts, IO callbacks, and idle functions) are made outside of the GTK+ lock. So, within a signal handler you do not need to call gdk_threads_enter(), but within the other types of callbacks, you do.

But my timeout function (for testing purposes) only prints in the console, so I don't think it's a problem of resource protection and mutexes.

The thread structure is:

Main thread --> no GLib main context explicitly created

  • capture thread

  • process thread --> should have a GLib main context and a timeout source

  • show thread

I appreciate any help.

Thanks in advance.

Tiffanitiffanie answered 1/7, 2012 at 23:3 Comment(1)
There is nothing fundamentally wrong with the concept of adding a timeout from a thread. Could you post a test case?Toscanini
C
1

Do you use g_timeout_add() or g_source_attach()?

g_timeout_add() and g_timeout_add_full() does not allow you to specify which main context to add. It always use the default main context. if you are not using the default main context in your main thread, it is perfectly ok to use it in your process thread. You can read about it in the description.

A GMainContext can only be running in a single thread

The default main context is implicitly created by many functions, including g_main_context_default(). So please make sure that you have not using it in your main thread.

You can use g_source_attach() to add a timeout source to your own main context if you decided to do so. There is no timeout function you can use to specify your main context. So, just do it by your self.

The following code is basically same as: g_timeout_add_full(G_PRIORITY_DEFAULT, 100, func, l, notify);

#include <glib.h>

void notify(gpointer data)
{
        g_main_loop_quit((GMainLoop *)data);
}

gboolean func(gpointer data)
{
        static gint i = 0;
        g_message("%d", i++);
        return (i < 10) ? TRUE : FALSE;
}

gpointer thread(gpointer data)
{
        GMainContext *c;
        GMainContext *d;
        GMainLoop *l;
        GSource *s;

        c = g_main_context_new();
        d = g_main_context_default();

        g_message("local: %p", c);
        g_message("default: %p", d);

#if 1
        l = g_main_loop_new(c, FALSE);
        s = g_timeout_source_new(100);
        g_source_set_callback(s, func, l, notify);
        g_source_attach(s, c);
        g_source_unref(s);
#else
        l = g_main_loop_new(d, FALSE);
        g_timeout_add_full(G_PRIORITY_DEFAULT, 100, func, l, notify);
#endif

        g_main_loop_run(l);
        g_message("done");

        return NULL;
}

int main(int argc, char *argv[])
{
        GError *error = NULL;
        GThread *t;

        g_thread_init(NULL);
        t = g_thread_create(thread, NULL, TRUE, &error);
        g_thread_join(t);

        return 0;
}
Cellulous answered 4/8, 2012 at 16:13 Comment(3)
I found your answer very useful. I have a question. I have main thread which calls g_io_watch several times. I have a thread which runs g_main_loop(). The purpose of thread is continuously look for events and dispatch them. But i am getting the results what I should get.Brisson
Not sure what you mean. But you can always create a new question ;-)Cellulous
Here it is. Have a look. #42396344Brisson

© 2022 - 2024 — McMap. All rights reserved.