On Fri, 6 Aug 2004 08:30:32 -0400, Daniel Nilsson <daniel@xxxxxxxxxxxxxxx> wrote: > Any thoughts of a easier way to do this ? Could I use the glib > GIOChannel somehow or coud the glib Asynchronous Queues help in any > way ? Paul Pogonyshev made a very helpful post about this a few days ago on gtk-app-devel: he includes a scrap of code which shows how to get a worker thread to trigger a callback in the GUI thread using GAsyncQueue and a GIOChannel. I was using pipes for this, but the win32 gtk seems to have some trouble with pipes as io sources, so I've switched to a variation on Paul's code for my app. Works great on *nix and win. So, in your case, I'd suggest a GUI thread and two worker threads. The workers signal to the GUI thread update the display using some variant on this thing. (I hope the repeat post doesn't annoy anyone, it'll save Daniel from hunting through the mailing list archive) ---------- Forwarded message ---------- From: Paul Pogonyshev Date: Wed, 14 Jul 2004 16:27:22 +0300 Subject: Re: Proper way to provide gtk+ app with asynchronous data? To: gtk-app-devel-list@xxxxxxxxx Russell Shaw wrote: > I'm trying to figure out how to wake up the main gtk gui thread when > new data is available in a GAsyncQueue (command_queue), so that i can > display the data in a gtk widget: Here is an excerpt from Quarry (http://home.gna.org/quarry/) that does exactly what you described. The larger part of code below is the main thread's code that deals with incoming "messages". To send some data from another thread, just do something like this: event_data = g_malloc(sizeof(ThreadEventData)); event_data->callback = some_callback; event_data->data = some_result_of_long_computation; g_async_queue_push(thread_events_queue, event_data); g_main_context_wakeup(NULL); Then `some_callback' will be invoked in main thread's context with `some_result_of_long_computation' pointer as argument. Depending on the implicit "message" you send, the callback should or should not g_free() its argument (if you send messages only when a thread terminates, then it certainly should free). Paul typedef void (* ThreadEventCallback) (void *result); typedef struct _ThreadEventData ThreadEventData; struct _ThreadEventData { ThreadEventCallback callback; void *result; }; static GSourceFuncs thread_events_functions = { thread_events_prepare, thread_events_check, thread_events_dispatch, NULL, }; static GSource *thread_events; GAsyncQueue *thread_events_queue; static gboolean thread_event_callback(gpointer data) { ThreadEventData *thread_completion_data = (ThreadEventData *) data; thread_completion_data->callback(thread_completion_data->result); return TRUE; } static gboolean thread_events_prepare(GSource *source, gint *timeout) { UNUSED(source); *timeout = -1; return g_async_queue_length(thread_events_queue) > 0; } static gboolean thread_events_check(GSource *source) { UNUSED(source); return g_async_queue_length(thread_events_queue) > 0; } static gboolean thread_events_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { gpointer data = g_async_queue_pop(thread_events_queue); gboolean result = callback(data); UNUSED(source); UNUSED(user_data); g_free(data); return result; } /* Somewhere before gtk_main() call. */ thread_events_queue = g_async_queue_new(); thread_events = g_source_new(&thread_events_functions, sizeof(GSource)); g_source_set_callback(thread_events, thread_event_callback, NULL, NULL); g_source_attach(thread_events, NULL); ... gtk_main(); ... /* And somewhere after it destroy the queue. */ g_source_destroy(thread_events); g_async_queue_unref(thread_events_queue); _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list