Re: Proper way to provide gtk+ app with asynchronous data?
- From: Russell Shaw <rjshaw netspace net au>
- Cc: gtk-app-devel-list gnome org
- Subject: Re: Proper way to provide gtk+ app with asynchronous data?
- Date: Thu, 15 Jul 2004 02:36:34 +1000
Paul Pogonyshev wrote:
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...
Thanks so much Paul.P, Todd.F, been wondering for months;)
-----------------------------------------------------------------------
#include<glib.h>
#include<glib/gprintf.h>
#include<gtk/gtk.h>
#include<gtk/gtksignal.h>
static gboolean thread_events_callback(gpointer data);
static gboolean thread_events_prepare(GSource *source, gint *timeout);
static gboolean thread_events_check(GSource *source);
static gboolean thread_events_dispatch(GSource *source, GSourceFunc callback,
gpointer user_data);
static GtkWidget *label;
static GSource *thread_events_source;
GAsyncQueue *thread_events_queue;
typedef void (*ThreadEventCallback)(GtkWidget *label, gint result);
typedef struct _ThreadEventData ThreadEventData;
struct _ThreadEventData{
ThreadEventCallback callback;
GtkWidget *label;
gint result;
};
static GSourceFuncs thread_events_functions={
thread_events_prepare,
thread_events_check,
thread_events_dispatch,
NULL,
};
gboolean
on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gtk_main_quit();
g_printf("quit\n");
return FALSE;
}
static void
label_cb(GtkWidget *label, gint result)
{
gchar str[10];
g_snprintf(str,10,"i:%d\n",result);
gtk_label_set_text(GTK_LABEL(label),str);
// gdk_threads_enter();
// gtk_main_iteration_do(FALSE);
// gdk_threads_leave();
}
static gpointer
command_thread(gpointer data)
{
ThreadEventData *event_data;
gint i=0;
for(;;){
i++;
g_usleep(G_USEC_PER_SEC*0.1);
event_data=g_malloc(sizeof(ThreadEventData));
event_data->callback=label_cb;
event_data->label=label;
event_data->result=i;
g_async_queue_push(thread_events_queue, event_data);
g_main_context_wakeup(NULL);
}
return NULL;
}
static gboolean
thread_events_callback(gpointer data)
{
ThreadEventData *thread_completion_data=(ThreadEventData*)data;
thread_completion_data->callback(
thread_completion_data->label,
thread_completion_data->result);
return TRUE;
}
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);
g_free(data);
return result;
}
static gboolean
thread_events_prepare(GSource *source, gint *timeout)
{
*timeout=-1;
return g_async_queue_length(thread_events_queue)>0;
}
static gboolean
thread_events_check(GSource *source)
{
return g_async_queue_length(thread_events_queue)>0;
}
int
main(int argc, char *argv[])
{
g_thread_init(NULL);
gdk_threads_init();
gtk_init(&argc,&argv);
GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
label=gtk_label_new("");
gtk_container_add(GTK_CONTAINER(window),label);
gtk_widget_show_all(window);
g_signal_connect(window,"delete-event",G_CALLBACK(on_destroy),NULL);
g_signal_connect(window,"destroy-event",G_CALLBACK(on_destroy),NULL);
thread_events_queue=g_async_queue_new();
g_thread_create(command_thread,NULL,FALSE,NULL);
thread_events_source=
g_source_new(&thread_events_functions,sizeof(GSource));
g_source_set_callback(
thread_events_source,
thread_events_callback,
NULL,
NULL
);
g_source_attach(thread_events_source,NULL);
gtk_main();
g_source_destroy(thread_events_source);
g_async_queue_unref(thread_events_queue);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]