Hi, On Tue, 15 Mar 2005 09:57:24 +0000, Athanasios Anastasiou <[EMAIL PROTECTED]> wrote: > Also could it be better that i add an expose_event handler to the widget > i want to draw and just post invalidate messages towards the widget from > the thread?
I do something similar in my app. I have a structure like this: - realtime thread runs and produces a packet of data every 20ms - it posts a pointer to the packet into a GAsyncQueue - the GAsyncQueue is connected to my GUI app (magic code below) ... a callback is triggered for each data item that arrives on the queue - the callback uses the packet of data to update the app's model, calculates what parts of the screen will be affected, invalidates those widgets / parts of widgets, and frees the packet - the "expose" handler is called at some later point and draws the current state of the model to the screen This maybe sounds complicated, but it's not that much code. You're guaranteed not to drop any packets, and the screen repaints can never fall behind the updates. If the system becomes heavily loaded, you'll just see a lower FPS for screen painting. Plus all your GUI code is single-threaded, much simpler! I used to use pipes for this, but I had problems getting the thing working on the win32 version of GTK. The AsyncQueue code comes from a very helpful post by Paul Pogonyshev last year. I've pasted it below to save you searching the archives (hope no one minds). Finally, you asked about books on GTK. The most up to date one I know is the GNOME2 developer's guide. It has a long and rather good section on GTK/GObject/GLib etc: http://www.amazon.com/exec/obidos/tg/detail/-/1593270305/102-1804772-0460922 http://www.nostarch.com/frameset.php?startat=gnome ---------- 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@gnome.org 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@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list