[glick2] Add forgotten files



commit 738186f5209460abcc7dd2a63120225d496edee2
Author: Alexander Larsson <alexl redhat com>
Date:   Wed Nov 30 11:39:46 2011 +0100

    Add forgotten files

 dbus-utils.c |  498 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dbus-utils.h |    4 +
 2 files changed, 502 insertions(+), 0 deletions(-)
---
diff --git a/dbus-utils.c b/dbus-utils.c
new file mode 100644
index 0000000..b15e47a
--- /dev/null
+++ b/dbus-utils.c
@@ -0,0 +1,498 @@
+#include "config.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+#include "dbus-utils.h"
+
+static void
+_g_dbus_oom (void)
+{
+  g_error ("DBus failed with out of memory error");
+}
+
+typedef gboolean (*GFDSourceFunc) (gpointer data,
+				   GIOCondition condition,
+				   int fd);
+
+/*************************************************************************
+ *             Helper fd source                                          *
+ ************************************************************************/
+
+typedef struct 
+{
+  GSource source;
+  GPollFD pollfd;
+  GCancellable *cancellable;
+  gulong cancelled_tag;
+} FDSource;
+
+static gboolean 
+fd_source_prepare (GSource  *source,
+		   gint     *timeout)
+{
+  FDSource *fd_source = (FDSource *)source;
+  *timeout = -1;
+  
+  return g_cancellable_is_cancelled (fd_source->cancellable);
+}
+
+static gboolean 
+fd_source_check (GSource  *source)
+{
+  FDSource *fd_source = (FDSource *)source;
+
+  return
+    g_cancellable_is_cancelled  (fd_source->cancellable) ||
+    fd_source->pollfd.revents != 0;
+}
+
+static gboolean
+fd_source_dispatch (GSource     *source,
+		    GSourceFunc  callback,
+		    gpointer     user_data)
+
+{
+  GFDSourceFunc func = (GFDSourceFunc)callback;
+  FDSource *fd_source = (FDSource *)source;
+
+  g_assert (func != NULL);
+
+  return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
+}
+
+static void 
+fd_source_finalize (GSource *source)
+{
+  FDSource *fd_source = (FDSource *)source;
+
+  if (fd_source->cancelled_tag)
+    g_cancellable_disconnect (fd_source->cancellable,
+			      fd_source->cancelled_tag);
+
+  if (fd_source->cancellable)
+    g_object_unref (fd_source->cancellable);
+}
+
+static GSourceFuncs fd_source_funcs = {
+  fd_source_prepare,
+  fd_source_check,
+  fd_source_dispatch,
+  fd_source_finalize
+};
+
+/* Might be called on another thread */
+static void
+fd_source_cancelled_cb (GCancellable *cancellable,
+			gpointer data)
+{
+  /* Wake up the mainloop in case we're waiting on async calls with FDSource */
+  g_main_context_wakeup (NULL);
+}
+
+/* Two __ to avoid conflict with gio version */
+static GSource *
+__g_fd_source_new (int fd,
+		   gushort events,
+		   GCancellable *cancellable)
+{
+  GSource *source;
+  FDSource *fd_source;
+
+  source = g_source_new (&fd_source_funcs, sizeof (FDSource));
+  fd_source = (FDSource *)source;
+
+  if (cancellable)
+    fd_source->cancellable = g_object_ref (cancellable);
+  
+  fd_source->pollfd.fd = fd;
+  fd_source->pollfd.events = events;
+  g_source_add_poll (source, &fd_source->pollfd);
+
+  if (cancellable)
+    fd_source->cancelled_tag =
+      g_cancellable_connect (cancellable,
+			     (GCallback)fd_source_cancelled_cb,
+			     NULL, NULL);
+  
+  return source;
+}
+
+static gint32 main_integration_data_slot = -1;
+static GOnce once_init_main_integration = G_ONCE_INIT;
+
+/**
+ * A GSource subclass for dispatching DBusConnection messages.
+ * We need this on top of the IO handlers, because sometimes
+ * there are messages to dispatch queued up but no IO pending.
+ * 
+ * The source is owned by the connection (and the main context
+ * while that is alive)
+ */
+typedef struct 
+{
+  GSource source;
+  
+  DBusConnection *connection;
+  GSList *ios;
+  GSList *timeouts;
+} DBusSource;
+
+typedef struct
+{
+  DBusSource *dbus_source;
+  GSource *source;
+  DBusWatch *watch;
+} IOHandler;
+
+typedef struct
+{
+  DBusSource *dbus_source;
+  GSource *source;
+  DBusTimeout *timeout;
+} TimeoutHandler;
+
+static gpointer
+main_integration_init (gpointer arg)
+{
+  if (!dbus_connection_allocate_data_slot (&main_integration_data_slot))
+    g_error ("Unable to allocate data slot");
+
+  return NULL;
+}
+
+static gboolean
+dbus_source_prepare (GSource *source,
+		     gint    *timeout)
+{
+  DBusConnection *connection = ((DBusSource *)source)->connection;
+  
+  *timeout = -1;
+
+  return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);  
+}
+
+static gboolean
+dbus_source_check (GSource *source)
+{
+  return FALSE;
+}
+
+static gboolean
+dbus_source_dispatch (GSource     *source,
+		      GSourceFunc  callback,
+		      gpointer     user_data)
+{
+  DBusConnection *connection = ((DBusSource *)source)->connection;
+
+  dbus_connection_ref (connection);
+
+  /* Only dispatch once - we don't want to starve other GSource */
+  dbus_connection_dispatch (connection);
+  
+  dbus_connection_unref (connection);
+
+  return TRUE;
+}
+
+static gboolean
+io_handler_dispatch (gpointer data,
+                     GIOCondition condition,
+                     int fd)
+{
+  IOHandler *handler = data;
+  guint dbus_condition = 0;
+  DBusConnection *connection;
+
+  connection = handler->dbus_source->connection;
+  
+  if (connection)
+    dbus_connection_ref (connection);
+  
+  if (condition & G_IO_IN)
+    dbus_condition |= DBUS_WATCH_READABLE;
+  if (condition & G_IO_OUT)
+    dbus_condition |= DBUS_WATCH_WRITABLE;
+  if (condition & G_IO_ERR)
+    dbus_condition |= DBUS_WATCH_ERROR;
+  if (condition & G_IO_HUP)
+    dbus_condition |= DBUS_WATCH_HANGUP;
+
+  /* Note that we don't touch the handler after this, because
+   * dbus may have disabled the watch and thus killed the
+   * handler.
+   */
+  dbus_watch_handle (handler->watch, dbus_condition);
+  handler = NULL;
+
+  if (connection)
+    dbus_connection_unref (connection);
+  
+  return TRUE;
+}
+
+static void
+io_handler_free (IOHandler *handler)
+{
+  DBusSource *dbus_source;
+  
+  dbus_source = handler->dbus_source;
+  dbus_source->ios = g_slist_remove (dbus_source->ios, handler);
+  
+  g_source_destroy (handler->source);
+  g_source_unref (handler->source);
+  g_free (handler);
+}
+
+static void
+dbus_source_add_watch (DBusSource *dbus_source,
+		       DBusWatch *watch)
+{
+  guint flags;
+  GIOCondition condition;
+  IOHandler *handler;
+  int fd;
+
+  if (!dbus_watch_get_enabled (watch))
+    return;
+  
+  g_assert (dbus_watch_get_data (watch) == NULL);
+  
+  flags = dbus_watch_get_flags (watch);
+
+  condition = G_IO_ERR | G_IO_HUP;
+  if (flags & DBUS_WATCH_READABLE)
+    condition |= G_IO_IN;
+  if (flags & DBUS_WATCH_WRITABLE)
+    condition |= G_IO_OUT;
+
+  handler = g_new0 (IOHandler, 1);
+  handler->dbus_source = dbus_source;
+  handler->watch = watch;
+
+#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1)
+  fd = dbus_watch_get_unix_fd (watch);
+#else
+  fd = dbus_watch_get_fd (watch);
+#endif
+    
+  handler->source = __g_fd_source_new (fd, condition, NULL);
+  g_source_set_callback (handler->source,
+			 (GSourceFunc) io_handler_dispatch, handler,
+                         NULL);
+  g_source_attach (handler->source, NULL);
+ 
+  dbus_source->ios = g_slist_prepend (dbus_source->ios, handler);
+  dbus_watch_set_data (watch, handler,
+		       (DBusFreeFunction)io_handler_free);
+}
+
+static void
+dbus_source_remove_watch (DBusSource *dbus_source,
+			  DBusWatch *watch)
+{
+  dbus_watch_set_data (watch, NULL, NULL);
+}
+
+static void
+timeout_handler_free (TimeoutHandler *handler)
+{
+  DBusSource *dbus_source;
+
+  dbus_source = handler->dbus_source;
+  dbus_source->timeouts = g_slist_remove (dbus_source->timeouts, handler);
+
+  g_source_destroy (handler->source);
+  g_source_unref (handler->source);
+  g_free (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer      data)
+{
+  TimeoutHandler *handler = data;
+
+  dbus_timeout_handle (handler->timeout);
+  
+  return TRUE;
+}
+
+static void
+dbus_source_add_timeout (DBusSource *dbus_source,
+			 DBusTimeout *timeout)
+{
+  TimeoutHandler *handler;
+  
+  if (!dbus_timeout_get_enabled (timeout))
+    return;
+  
+  g_assert (dbus_timeout_get_data (timeout) == NULL);
+
+  handler = g_new0 (TimeoutHandler, 1);
+  handler->dbus_source = dbus_source;
+  handler->timeout = timeout;
+
+  handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+  g_source_set_callback (handler->source,
+			 timeout_handler_dispatch, handler,
+                         NULL);
+  g_source_attach (handler->source, NULL);
+
+  /* handler->source is owned by the context here */
+  dbus_source->timeouts = g_slist_prepend (dbus_source->timeouts, handler);
+
+  dbus_timeout_set_data (timeout, handler,
+			 (DBusFreeFunction)timeout_handler_free);
+}
+
+static void
+dbus_source_remove_timeout (DBusSource *source,
+			    DBusTimeout *timeout)
+{
+  dbus_timeout_set_data (timeout, NULL, NULL);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+	   gpointer   data)
+{
+  DBusSource *dbus_source = data;
+
+  dbus_source_add_watch (dbus_source, watch);
+  
+  return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch,
+	      gpointer   data)
+{
+  DBusSource *dbus_source = data;
+
+  dbus_source_remove_watch (dbus_source, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch,
+               void      *data)
+{
+  /* Because we just exit on OOM, enable/disable is
+   * no different from add/remove */
+  if (dbus_watch_get_enabled (watch))
+    add_watch (watch, data);
+  else
+    remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+	     void        *data)
+{
+  DBusSource *source = data;
+  
+  if (!dbus_timeout_get_enabled (timeout))
+    return TRUE;
+
+  dbus_source_add_timeout (source, timeout);
+
+  return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+		void        *data)
+{
+  DBusSource *source = data;
+
+  dbus_source_remove_timeout (source, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout,
+                 void        *data)
+{
+  /* Because we just exit on OOM, enable/disable is
+   * no different from add/remove
+   */
+  if (dbus_timeout_get_enabled (timeout))
+    add_timeout (timeout, data);
+  else
+    remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+  g_main_context_wakeup (NULL);
+}
+
+static const GSourceFuncs dbus_source_funcs = {
+  dbus_source_prepare,
+  dbus_source_check,
+  dbus_source_dispatch
+};
+
+/* Called when the connection dies or when we're unintegrating from mainloop */
+static void
+dbus_source_free (DBusSource *dbus_source)
+{
+  while (dbus_source->ios)
+    {
+      IOHandler *handler = dbus_source->ios->data;
+      
+      dbus_watch_set_data (handler->watch, NULL, NULL);
+    }
+
+  while (dbus_source->timeouts)
+    {
+      TimeoutHandler *handler = dbus_source->timeouts->data;
+      
+      dbus_timeout_set_data (handler->timeout, NULL, NULL);
+    }
+
+  /* Remove from mainloop */
+  g_source_destroy ((GSource *)dbus_source);
+
+  g_source_unref ((GSource *)dbus_source);
+}
+
+void
+_g_dbus_connection_integrate_with_main  (DBusConnection *connection)
+{
+  DBusSource *dbus_source;
+
+  g_once (&once_init_main_integration, main_integration_init, NULL);
+  
+  g_assert (connection != NULL);
+
+  dbus_source = (DBusSource *)
+    g_source_new ((GSourceFuncs*)&dbus_source_funcs,
+		  sizeof (DBusSource));
+  
+  dbus_source->connection = connection;
+  
+  if (!dbus_connection_set_watch_functions (connection,
+                                            add_watch,
+                                            remove_watch,
+                                            watch_toggled,
+                                            dbus_source, NULL))
+    _g_dbus_oom ();
+
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              add_timeout,
+                                              remove_timeout,
+                                              timeout_toggled,
+                                              dbus_source, NULL))
+    _g_dbus_oom ();
+    
+  dbus_connection_set_wakeup_main_function (connection,
+					    wakeup_main,
+					    dbus_source, NULL);
+
+  /* Owned by both connection and mainloop (until destroy) */
+  g_source_attach ((GSource *)dbus_source, NULL);
+
+  if (!dbus_connection_set_data (connection,
+				 main_integration_data_slot,
+				 dbus_source, (DBusFreeFunction)dbus_source_free))
+    _g_dbus_oom ();
+}
diff --git a/dbus-utils.h b/dbus-utils.h
new file mode 100644
index 0000000..589fbde
--- /dev/null
+++ b/dbus-utils.h
@@ -0,0 +1,4 @@
+#include <dbus/dbus.h>
+
+void _g_dbus_connection_integrate_with_main  (DBusConnection *connection);
+



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