[dconf] Bug 396998 - asynchronous early-error dispatch



commit e7498e478932975569a85fb1c209e94b8f780d15
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Oct 6 21:36:02 2009 -0400

    Bug 396998 - asynchronous early-error dispatch
    
    Add code to dbus backend to dispatch errors.

 dconf/dconf-core.c |   12 +++--
 dconf/dconf-dbus.c |  122 +++++++++++++++++++++++++++++++++++-----------------
 dconf/dconf-dbus.h |    4 +-
 3 files changed, 94 insertions(+), 44 deletions(-)
---
diff --git a/dconf/dconf-core.c b/dconf/dconf-core.c
index 95059b4..e62acb3 100644
--- a/dconf/dconf-core.c
+++ b/dconf/dconf-core.c
@@ -565,8 +565,10 @@ dconf_merge_async (const gchar             *prefix,
 
     if (!dconf_check_tree_writable (mount, prefix, tree, &error))
       {
-        g_assert_not_reached ();
-        // XXX dispatch in idle...
+        dconf_dbus_dispatch_error ((DConfDBusAsyncReadyCallback) callback,
+                                   user_data, error);
+        g_error_free (error);
+        return;
       }
   }
 
@@ -634,8 +636,10 @@ dconf_set_async (const gchar             *key,
 
     if (!dconf_check_writable (mount, key, &error))
       {
-        g_assert_not_reached ();
-        // XXX dispatch in idle...
+        dconf_dbus_dispatch_error ((DConfDBusAsyncReadyCallback) callback,
+                                   user_data, error);
+        g_error_free (error);
+        return;
       }
   }
 
diff --git a/dconf/dconf-dbus.c b/dconf/dconf-dbus.c
index f2d5ac7..a174eda 100644
--- a/dconf/dconf-dbus.c
+++ b/dconf/dconf-dbus.c
@@ -525,6 +525,7 @@ dconf_dbus_blocking_call (DConfDBus    *bus,
 typedef struct
 {
   DConfDBus *bus;
+  GError *error;
   DConfDBusAsyncReadyCallback callback;
   GMainContext *context;
   DBusPendingCall *pending;
@@ -534,25 +535,43 @@ typedef struct
 struct OPAQUE_TYPE__DConfDBusAsyncResult
 {
   DConfDBus *bus;
+  GError *error;
   DBusPendingCall *pending;
 };
 
 static DConfDBusClosure *
 dconf_dbus_closure_new (DConfDBus                   *bus,
-                        DConfDBusAsyncReadyCallback  callback,
                         DBusPendingCall             *pending,
+                        GError                      *error,
+                        DConfDBusAsyncReadyCallback  callback,
                         gpointer                     user_data)
 {
   DConfDBusClosure *closure;
+  GMainContext *context;
+
+  g_assert ((error == NULL) ^ (pending == NULL));
+
+  context = g_main_context_get_thread_default ();
 
   closure = g_slice_new (DConfDBusClosure);
   closure->bus = bus;
   closure->callback = callback;
-  closure->pending = dbus_pending_call_ref (pending);
   closure->user_data = user_data;
-  closure->context = g_main_context_get_thread_default ();
-  if (closure->context)
-    g_main_context_ref (closure->context);
+
+  if (context)
+    closure->context = g_main_context_ref (context);
+  else
+    closure->context = NULL;
+
+  if (error)
+    closure->error = g_error_copy (error);
+  else
+    closure->error = NULL;
+
+  if (pending)
+    closure->pending = dbus_pending_call_ref (pending);
+  else
+    closure->pending = NULL;
 
   return closure;
 }
@@ -565,12 +584,17 @@ dconf_dbus_closure_fire (gpointer user_data)
 
   result.bus = closure->bus;
   result.pending = closure->pending;
+  result.error = closure->error;
 
   closure->callback (&result, closure->user_data);
 
-  dbus_pending_call_unref (closure->pending);
+  if (closure->pending)
+    dbus_pending_call_unref (closure->pending);
   if (closure->context)
     g_main_context_unref (closure->context);
+  if (closure->error)
+    g_error_free (closure->error);
+
   g_slice_free (DConfDBusClosure, closure);
 
   return FALSE;
@@ -600,8 +624,8 @@ dconf_dbus_async_call (DConfDBus                   *bus,
 
   dbus_connection_send_with_reply (bus->connection, message, &pending, -1);
   dbus_pending_call_set_notify (pending, dconf_dbus_async_ready,
-                                dconf_dbus_closure_new (bus, callback,
-                                                        pending, user_data),
+                                dconf_dbus_closure_new (bus, pending, NULL,
+                                                        callback, user_data),
                                 NULL);
   dbus_pending_call_unref (pending);
   dbus_message_unref (message);
@@ -817,51 +841,71 @@ dconf_dbus_async_finish (DConfDBusAsyncResult  *result,
   DBusMessage *reply;
   gboolean success;
 
-  reply = dbus_pending_call_steal_reply (result->pending);
-  if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
-    {
-      const gchar *code, *message;
-      gboolean have_message;
-
-      code = dbus_message_get_error_name (reply);
-
-      have_message = dbus_message_get_args (reply, NULL,
-                                            DBUS_TYPE_STRING, &message,
-                                            DBUS_TYPE_INVALID);
-
-      if (have_message)
-        g_set_error (error, 0, 0, "%s: %s", code, message);
-      else
-        g_set_error (error, 0, 0, "DBus error: %s", code);
-
-      success = FALSE;
-    }
-  else if (!dbus_message_has_signature (reply, signature))
+  if (result->error)
     {
-      g_set_error (error, 0, 0, "unexpected signature in DBus reply");
+      g_propagate_error (error, result->error);
+      result->error = NULL;
       success = FALSE;
     }
   else
     {
-      if (event_id)
+      reply = dbus_pending_call_steal_reply (result->pending);
+      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
         {
-          guint32 sequence;
+          const gchar *code, *message;
+          gboolean have_message;
+
+          code = dbus_message_get_error_name (reply);
+
+          have_message = dbus_message_get_args (reply, NULL,
+                                                DBUS_TYPE_STRING, &message,
+                                                DBUS_TYPE_INVALID);
+
+          if (have_message)
+            g_set_error (error, 0, 0, "%s: %s", code, message);
+          else
+            g_set_error (error, 0, 0, "DBus error: %s", code);
 
-          dbus_message_get_args (reply, NULL,
-                                 DBUS_TYPE_UINT32, &sequence,
-                                 DBUS_TYPE_INVALID);
-          *event_id = dconf_dbus_format_event_id (result->bus,
-                                                  reply, sequence);
+          success = FALSE;
+        }
+      else if (!dbus_message_has_signature (reply, signature))
+        {
+          g_set_error (error, 0, 0, "unexpected signature in DBus reply");
+          success = FALSE;
+        }
+      else
+        {
+          if (event_id)
+            {
+              guint32 sequence;
+
+              dbus_message_get_args (reply, NULL,
+                                     DBUS_TYPE_UINT32, &sequence,
+                                     DBUS_TYPE_INVALID);
+              *event_id = dconf_dbus_format_event_id (result->bus,
+                                                      reply, sequence);
+            }
+
+          success = TRUE;
         }
 
-      success = TRUE;
+      dbus_message_unref (reply);
     }
 
-  dbus_message_unref (reply);
-
   return success;
 }
 
+void
+dconf_dbus_dispatch_error (DConfDBusAsyncReadyCallback  callback,
+                           gpointer                     user_data,
+                           GError                      *error)
+{
+  DConfDBusClosure *closure;
+
+  closure = dconf_dbus_closure_new (NULL, NULL, error, callback, user_data);
+  g_idle_add (dconf_dbus_closure_fire, closure);
+}
+
 /* ------------------------------------------------------------------------ */
 /* all code past this point is for mainloop integration.
  *
diff --git a/dconf/dconf-dbus.h b/dconf/dconf-dbus.h
index d9351fd..b506c22 100644
--- a/dconf/dconf-dbus.h
+++ b/dconf/dconf-dbus.h
@@ -82,6 +82,8 @@ void                    dconf_dbus_unwatch                              (DConfDB
                                                                          const gchar                  *prefix,
                                                                          DConfDBusNotify               callback,
                                                                          gpointer                      user_data);
-
+void                    dconf_dbus_dispatch_error                       (DConfDBusAsyncReadyCallback   callback,
+                                                                         gpointer                      user_data,
+                                                                         GError                       *error);
 
 #endif /* _dconf_dbus_h_ */



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