Re: Async communication



On Fri, 6 Aug 2004 08:30:32 -0400, Daniel Nilsson
<daniel oden homeip net> 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 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]