My audio-recorder that was based on GTK2 had some threads that also modified the GUI-elements. I had to call GDK_THREADS_ENTER<https://developer.gnome.org/gdk3/3.10/gdk3-Threads.html#GDK-THREADS-ENTER:CAPS> / GDK_THREADS_LEAVE<https://developer.gnome.org/gdk3/3.10/gdk3-Threads.html#GDK-THREADS-ENTER:CAPS> before modifying the GTK-elements, otherwise the GUI froze.
Now in GTK3, I've replaced the threads with g_timeout_add_full<https://developer.gnome.org/glib/2.30/glib-The-Main-Event-Loop.html#g-timeout-add-full> () and GAsyncQueue<https://developer.gnome.org/glib/2.26/glib-Asynchronous-Queues.html#GAsyncQueue> . g_timeout_full_id() runs within the MainLoop so GUI-locking is handled automatically. The code is here: http://bazaar.launchpad.net/~osmoma/audio-recorder/trunk/view/head:/src/rec-manager.c The recorder receives commands (like: start/stop/pause/etc.) from various modules and sources. All commands go through the GAsyncQueue. Bom dia Osmo (Moma) Antero On Thu, Nov 28, 2013 at 3:32 AM, David Buchan <pdbuc...@yahoo.com> wrote: > > > David Buchan <pdbuc...@yahoo.com> wrote: > > Hi Michael, > > > > My 32-bit, GTK+2 version does > > > > // Secure glib > > if (!g_thread_supported ()) { > > g_thread_init (NULL); > > } > > > > at the beginning, and then the thread is spawned via: > > > > > on_button1_clicked (GtkButton *button1, MyData *data) > > { > > GThread *thread; > > GError *error = NULL; > > > > thread = g_thread_create ((GThreadFunc) my_function, data, FALSE, > > &error); if (! thread) { > > g_print ("Error: Unable to create new thread for my_function() > > in on_button1_clicked().%s\n", error->message); exit (EXIT_FAILURE); > > } > > > > My 64-bit, GTK+3 versions does not do the g_thread_init() call. > > > > It spawns a new thread via: > > > > int > > on_button1_clicked (GtkButton *button1, MyData *data) > > { > > GThread *thread; > > > > thread = g_thread_new ("my_function", (GThreadFunc) my_function, > > data); if (! thread) { > > fprintf (stderr, "Error: Unable to create new thread for > > my_function() in on_button1_clicked().\n"); exit (EXIT_FAILURE); > > } > > Show us your my_function(): you are almost certainly doing something > wrong. Best of all, provide a complete compilable example which > demonstrates the problem. And why are you casting the function pointer > to GThreadFunc? You do not need to call g_thread_init() with glib >= > 2.32, and you do with earlier versions. Prior to version 2.24 > g_thread_init() had to be the first glib call. Between 2.24 and 2.30 it > had to be the first > call relevant to threads. > > Also, please don't top post. > > Chris > ========================================== > Hi Chris, > > > I removed the call to g_thread_init() and it still works fine! Great catch > there. > > I had put the cast to GThreadFunc there because otherwise I get the > following error: > > callbacks.c: In function ‘on_button1_clicked’: > callbacks.c:3829: warning: passing argument 1 of ‘g_thread_create_full’ > from incompatible pointer type > /usr/include/glib-2.0/glib/gthread.h:225: note: expected ‘GThreadFunc’ but > argument is of type ‘int (*)(struct MyData *)’ > > I saw other people on the web do the cast as well to remove that error. Is > there a mistake in how I use g_thread_create()? I'd like to drop the cast > if I can. It seemed strange at the time I put it in. > > Top-posting is due to the way Yahoo mail handles replies. > Maybe this > is better, but it didn't put the >'s in, thus the "====..." line. I > dunno. Sorry about that. > > I'm still investigating the delay. The my_function() code is hundreds of > lines, so I'd need to create a small example to post. > Let me continue to investigate. > > Dave > > ========================== > ... and now I see what's going on. > > My newly spawned thread calls a function which starts a messaging > idle-function. > > [my main program] ---> [my new thread] ----> [post_message function] ===> > [update GUI idle function] > > In my new thread, I call: > > post_message (text, data); > > and that looks like: > > // Start an instance of activity_message() idle function. > int > post_message (char *message, MyData *data) > { > // Allocate memory for string; Idle function will free it. > data->activity_message = allocate_strmem (TEXTLEN); > // Copy message. > strncpy (data->activity_message, message, TEXTLEN - 1); // Minus 1 for > string termination. > > g_idle_add ((GSourceFunc) activity_message, data); > sleep (1); > return (EXIT_SUCCESS); > } > > // Idle function to add a message to the activity textview > // This idle function returns 0 in order to stop. > int > activity_message (MyData *data) > { > ... > Update a textview with our message ... > > return (0) > } > > I set it up this way so the GUI can be updated. > > The call to sleep() protects me against the situation in which my thread > makes a second call to post_message() when activity_message() hasn't > finished updating the GUI from the first call. > > Is there a way to have my thread call post_message() whenever it needs to, > and have the messages queue-up? > > Dave > _______________________________________________ > gtk-app-devel-list mailing list > gtk-app-devel-list@gnome.org > https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list > -- // moma http://www.futuredesktop.org _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list