Index: glib/glib.symbols
===================================================================
--- glib/glib.symbols	(revision 5522)
+++ glib/glib.symbols	(working copy)
@@ -73,6 +73,9 @@ g_async_queue_try_pop
 g_async_queue_try_pop_unlocked
 g_async_queue_unlock
 g_async_queue_unref
+g_async_queue_watch_source_new
+g_async_queue_watch_add_full
+g_async_queue_watch_add
 #ifndef G_DISABLE_DEPRECATED
 g_async_queue_ref_unlocked
 g_async_queue_unref_and_unlock
Index: glib/gasyncqueue.c
===================================================================
--- glib/gasyncqueue.c	(revision 5522)
+++ glib/gasyncqueue.c	(working copy)
@@ -35,6 +35,7 @@ struct _GAsyncQueue
   GMutex *mutex;
   GCond *cond;
   GQueue *queue;
+  GSList *watchers;
   guint waiting_threads;
   gint32 ref_count;
 };
@@ -58,6 +59,7 @@ g_async_queue_new (void)
   retval->mutex = g_mutex_new ();
   retval->cond = NULL;
   retval->queue = g_queue_new ();
+  retval->watchers = NULL;
   retval->waiting_threads = 0;
   retval->ref_count = 1;
   return retval;
@@ -203,6 +205,12 @@ g_async_queue_push (GAsyncQueue* queue, 
   g_mutex_unlock (queue->mutex);
 }
 
+static void
+wakeup_sources (GSource *source)
+{
+  g_main_context_wakeup (source->context);
+}
+
 /**
  * g_async_queue_push_unlocked:
  * @queue: a #GAsyncQueue.
@@ -221,6 +229,7 @@ g_async_queue_push_unlocked (GAsyncQueue
   g_queue_push_head (queue->queue, data);
   if (queue->waiting_threads > 0)
     g_cond_signal (queue->cond);
+  g_slist_foreach (queue->watchers, (GFunc) wakeup_sources, NULL);
 }
 
 /**
@@ -310,6 +319,7 @@ g_async_queue_push_sorted_unlocked (GAsy
 			 &sd);
   if (queue->waiting_threads > 0)
     g_cond_signal (queue->cond);
+  g_slist_foreach (queue->watchers, (GFunc) wakeup_sources, NULL);
 }
 
 static gpointer
@@ -625,6 +635,179 @@ g_async_queue_sort_unlocked (GAsyncQueue
 		&sd);
 }
 
+typedef struct _GAsyncQueueWatchSource GAsyncQueueWatchSource;
+struct _GAsyncQueueWatchSource
+{
+  GSource      source;
+  GAsyncQueue *queue;
+};
+
+static gboolean
+g_async_queue_watch_check    (GSource  *abstract_source)
+{
+  GAsyncQueueWatchSource *source = (GAsyncQueueWatchSource *) abstract_source;
+  GAsyncQueue *queue = source->queue;
+  gboolean ret;
+
+  g_mutex_lock (queue->mutex);
+  ret = g_queue_peek_tail_link (queue->queue) != NULL;
+  g_mutex_unlock (queue->mutex);
+
+  return ret;
+}
+
+
+static gboolean
+g_async_queue_watch_prepare  (GSource  *source,
+		              gint     *timeout)
+{
+  *timeout = -1;
+
+  return g_async_queue_watch_check (source);
+}
+
+static gboolean
+g_async_queue_watch_dispatch (GSource    *abstract_source,
+		              GSourceFunc callback,
+			      gpointer    user_data)
+{
+  GAsyncQueueWatchSource *source = (GAsyncQueueWatchSource *) abstract_source;
+  GAsyncQueueWatchFunc watch_callback = (GAsyncQueueWatchFunc) callback;
+
+  if (!callback)
+    {
+      g_warning ("GAsyncQueue watch source dispatched without callback\n"
+		 "You must call g_source_set_callback().");
+      return FALSE;
+    }
+
+  return watch_callback (source->queue, user_data);
+}
+
+static void
+g_async_queue_watch_finalize    (GSource  *abstract_source)
+{
+  GAsyncQueueWatchSource *source = (GAsyncQueueWatchSource *) abstract_source;
+  GAsyncQueue *queue = source->queue;
+
+  g_mutex_lock (queue->mutex);
+  queue->watchers = g_slist_remove (queue->watchers, source);
+  g_mutex_unlock (queue->mutex);
+
+  g_async_queue_unref (queue);
+}
+
+static GSourceFuncs g_async_queue_watch_funcs =
+{
+  g_async_queue_watch_prepare,
+  g_async_queue_watch_check,
+  g_async_queue_watch_dispatch,
+  g_async_queue_watch_finalize
+};
+
+/**
+ * g_async_queue_watch_source_new:
+ * @queue: The GAsyncQueue to watch.
+ *
+ * Creates a new async_queue_watch source.
+ *
+ * The source will not initially be associated with any #GMainContext
+ * and must be added to one with g_source_attach() before it will be
+ * executed.
+ *
+ * The async_queue_watch is a source that will trigger a GMainLoop wakeup
+ * and dispatch when a value has been pushed to the queue.
+ *
+ * Return value: the newly-created child watch source
+ *
+ * Since: 2.14
+ **/
+GSource *
+g_async_queue_watch_source_new (GAsyncQueue *queue)
+{
+  GAsyncQueueWatchSource *source;
+
+  g_return_val_if_fail (queue != NULL, NULL);
+  g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, 0);
+
+  source = (GAsyncQueueWatchSource *) g_source_new (&g_async_queue_watch_funcs, sizeof (GAsyncQueueWatchSource));
+  source->queue   = g_async_queue_ref (queue);
+
+  g_mutex_lock (queue->mutex);
+  queue->watchers = g_slist_prepend (queue->watchers, source);
+  g_mutex_unlock (queue->mutex);
+
+  return &source->source;
+}
+
+
+/**
+ * g_async_queue_watch_add_full:
+ * @priority: the priority of the idle source. Typically this will be in the
+ *            range between #G_PRIORITY_DEFAULT_IDLE and #G_PRIORITY_HIGH_IDLE.
+ * @queue:    The #GAsyncQueue to watch
+ * @function: function to call
+ * @data:     data to pass to @function
+ * @notify:   function to call when the idle is removed, or %NULL
+ *
+ * Sets a function to be called when the #GASyncQueue indicated by @queue
+ * has had an element pushed to it, at the priority @priority.
+ *
+ * Return value: the ID (greater than 0) of the event source.
+ *
+ * Since: 2.14
+ **/
+guint
+g_async_queue_watch_add_full (gint                 priority,
+			      GAsyncQueue         *queue,
+			      GAsyncQueueWatchFunc function,
+			      gpointer             data,
+			      GDestroyNotify       notify)
+{
+  GSource *source;
+  guint id;
+
+  g_return_val_if_fail (queue != NULL, 0);
+  g_return_val_if_fail (function != NULL, 0);
+
+  source = g_async_queue_watch_source_new (queue);
+
+  if (priority != G_PRIORITY_DEFAULT)
+    g_source_set_priority (source, priority);
+
+  g_source_set_callback (source, (GSourceFunc) function, data, notify);
+  id = g_source_attach (source, NULL);
+  g_source_unref (source);
+
+  return id;
+}
+
+
+/**
+ * g_async_queue_watch_add:
+ * @queue:    The #GAsyncQueue to watch
+ * @function: function to call
+ * @data:     data to pass to @function
+ *
+ * Sets a function to be called when the #GASyncQueue indicated by @queue
+ * has had an element pushed to it, at the priority @priority.
+ *
+ * Return value: the ID (greater than 0) of the event source.
+ *
+ * Since: 2.14
+ **/
+guint
+g_async_queue_watch_add (GAsyncQueue         *queue,
+		         GAsyncQueueWatchFunc function,
+			 gpointer             data)
+{
+  return g_async_queue_watch_add_full (G_PRIORITY_DEFAULT,
+                                       queue,
+				       function,
+				       data,
+				       NULL);
+}
+
 /*
  * Private API
  */
Index: glib/gasyncqueue.h
===================================================================
--- glib/gasyncqueue.h	(revision 5522)
+++ glib/gasyncqueue.h	(working copy)
@@ -28,6 +28,7 @@
 #define __G_ASYNCQUEUE_H__
 
 #include <glib/gthread.h>
+#include <glib/gmain.h>
 
 G_BEGIN_DECLS
 
@@ -106,6 +107,19 @@ void         g_async_queue_sort_unlocked
 						 GCompareDataFunc  func,
 						 gpointer          user_data);
 
+/* Allow the GMainLoop to wait for data to be pushed to a queue. */
+typedef gboolean  (*GAsyncQueueWatchFunc)       (GAsyncQueue *queue,
+				                 gpointer data);
+GSource     *g_async_queue_watch_source_new     (GAsyncQueue         *queue);
+guint        g_async_queue_watch_add_full       (gint                 priority,
+			                         GAsyncQueue         *queue,
+						 GAsyncQueueWatchFunc function,
+						 gpointer             data,
+						 GDestroyNotify       notify);
+guint        g_async_queue_watch_add            (GAsyncQueue         *queue,
+						 GAsyncQueueWatchFunc function,
+						 gpointer             data);
+
 /* Private API */
 GMutex*      _g_async_queue_get_mutex           (GAsyncQueue      *queue);
 
