[gvfs] client: Port GDaemonFileEnumerator to GTask



commit 2eae1086656ebfa1b8eb20019636043a5e151c97
Author: Ondrej Holy <oholy redhat com>
Date:   Mon Jun 13 11:57:13 2016 +0200

    client: Port GDaemonFileEnumerator to GTask
    
    GSimpleAsyncResult is deprecated in favour of GTask and should be replaced.
    
    "changed" signal is added in order to allow splitting _sync and _async code
    paths to use GTask as user_data for _async functionality.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747412

 client/gdaemonfileenumerator.c |  190 ++++++++++++++++++++--------------------
 1 files changed, 95 insertions(+), 95 deletions(-)
---
diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c
index d056359..aa30ee2 100644
--- a/client/gdaemonfileenumerator.c
+++ b/client/gdaemonfileenumerator.c
@@ -58,7 +58,6 @@ struct _GDaemonFileEnumerator
   int async_requested_files;
   gulong cancelled_tag;
   guint timeout_tag;
-  GSimpleAsyncResult *async_res;
   GMainLoop *next_files_mainloop;
   GMainContext *next_files_context;
   GSource *next_files_sync_timeout_source;
@@ -68,6 +67,15 @@ struct _GDaemonFileEnumerator
   MetaTree *metadata_tree;
 };
 
+
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
 G_DEFINE_TYPE (GDaemonFileEnumerator, g_daemon_file_enumerator, G_TYPE_FILE_ENUMERATOR)
 
 static GFileInfo *       g_daemon_file_enumerator_next_file   (GFileEnumerator  *enumerator,
@@ -93,7 +101,6 @@ static void              g_daemon_file_enumerator_close_async (GFileEnumerator
 static gboolean          g_daemon_file_enumerator_close_finish (GFileEnumerator      *enumerator,
                                                               GAsyncResult         *result,
                                                               GError              **error);
-static void              trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok);
 
 
 static void
@@ -166,6 +173,13 @@ g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass)
   enumerator_class->close_fn = g_daemon_file_enumerator_close;
   enumerator_class->close_async = g_daemon_file_enumerator_close_async;
   enumerator_class->close_finish = g_daemon_file_enumerator_close_finish;
+
+  signals[CHANGED] = g_signal_new ("changed",
+                                   G_TYPE_FROM_CLASS (gobject_class),
+                                   G_SIGNAL_RUN_LAST,
+                                   0, NULL, NULL,
+                                   g_cclosure_marshal_VOID__VOID,
+                                   G_TYPE_NONE, 0);
 }
 
 static void
@@ -180,7 +194,7 @@ next_files_sync_check (GDaemonFileEnumerator *enumerator)
   g_mutex_unlock (&enumerator->next_files_mutex);
 }
 
-static gboolean
+static void
 handle_done (GVfsDBusEnumerator *object,
              GDBusMethodInvocation *invocation,
              gpointer user_data)
@@ -189,17 +203,15 @@ handle_done (GVfsDBusEnumerator *object,
 
   G_LOCK (infos);
   enumerator->done = TRUE;
-  if (enumerator->async_requested_files > 0)
-    trigger_async_done (enumerator, TRUE);
   next_files_sync_check (enumerator);
   G_UNLOCK (infos);
 
+  g_signal_emit (enumerator, signals[CHANGED], 0);
+
   gvfs_dbus_enumerator_complete_done (object, invocation);
-  
-  return TRUE;
 }
 
-static gboolean
+static void
 handle_got_info (GVfsDBusEnumerator *object,
                  GDBusMethodInvocation *invocation,
                  GVariant *arg_infos,
@@ -230,15 +242,12 @@ handle_got_info (GVfsDBusEnumerator *object,
   
   G_LOCK (infos);
   enumerator->infos = g_list_concat (enumerator->infos, infos);
-  if (enumerator->async_requested_files > 0 &&
-      g_list_length (enumerator->infos) >= enumerator->async_requested_files)
-    trigger_async_done (enumerator, TRUE);
   next_files_sync_check (enumerator);
   G_UNLOCK (infos);
 
+  g_signal_emit (enumerator, signals[CHANGED], 0);
+
   gvfs_dbus_enumerator_complete_got_info (object, invocation);
-  
-  return TRUE;
 }
 
 static void
@@ -362,34 +371,45 @@ add_metadata (GFileInfo *info,
   g_free (path);
 }
 
-static GCancellable *
-simple_async_result_get_cancellable (GSimpleAsyncResult *res)
+static gboolean
+_g_task_return_pointer_idle_cb (GTask *task)
 {
-  return g_object_get_data (G_OBJECT (res), "file-enumerator-cancellable");
+  gpointer result;
+  GDestroyNotify notify;
+
+  result = g_object_get_data (G_OBJECT (task), "_g_task_return_pointer_idle_result");
+  notify = g_object_get_data (G_OBJECT (task), "_g_task_return_pointer_idle_notify");
+  g_task_return_pointer (task, result, notify);
+
+  return FALSE;
 }
 
 static void
-simple_async_result_set_cancellable (GSimpleAsyncResult *res,
-                                     GCancellable       *cancellable)
+_g_task_return_pointer_idle (GTask *task, gpointer result, GDestroyNotify notify)
 {
-  if (!cancellable)
-    return;
+  GSource *source;
+
+  g_object_set_data (G_OBJECT (task), "_g_task_return_pointer_idle_result", result);
+  g_object_set_data (G_OBJECT (task), "_g_task_return_pointer_idle_notify", notify);
 
-  g_object_set_data_full (G_OBJECT (res),
-                          "file-enumerator-cancellable",
-                          g_object_ref (cancellable),
-                          g_object_unref);
+  source = g_idle_source_new ();
+  g_source_set_priority (source, g_task_get_priority (task));
+  g_source_set_callback (source, (GSourceFunc) _g_task_return_pointer_idle_cb,
+                         g_object_ref (task), g_object_unref);
+  g_source_attach (source, g_task_get_context (task));
+  g_source_unref (source);
 }
 
 /* Called with infos lock held */
 static void
-trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
+trigger_async_done (GTask *task, gboolean ok)
 {
-  GList *rest, *l;
-  
+  GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (g_task_get_source_object (task));
+  GList *rest, *l = NULL;
+
   if (daemon->cancelled_tag != 0)
     {
-      GCancellable *cancellable = simple_async_result_get_cancellable (daemon->async_res);
+      GCancellable *cancellable = g_task_get_cancellable (task);
 
       /* If ok, we're a normal callback on the main thread,
         ensure protection against a thread cancelling and
@@ -432,14 +452,12 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
       daemon->infos = rest;
 
       g_list_foreach (l, (GFunc)add_metadata, daemon);
-
-      g_simple_async_result_set_op_res_gpointer (daemon->async_res,
-                                                l,
-                                                (GDestroyNotify)free_info_list);
     }
 
-  g_simple_async_result_complete_in_idle (daemon->async_res);
-  
+  /* Result has to be returned in idle in order to avoid deadlock */
+  _g_task_return_pointer_idle (task, l, (GDestroyNotify) free_info_list);
+
+  g_signal_handlers_disconnect_by_data (daemon, task);
   daemon->cancelled_tag = 0;
 
   if (daemon->timeout_tag != 0)
@@ -447,9 +465,8 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
   daemon->timeout_tag = 0;
   
   daemon->async_requested_files = 0;
-  
-  g_object_unref (daemon->async_res);
-  daemon->async_res = NULL;
+
+  g_object_unref (task);
 }
 
 char  *
@@ -544,25 +561,30 @@ g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator,
 }
 
 static void
+async_changed (GTask *task)
+{
+  GDaemonFileEnumerator *enumerator = G_DAEMON_FILE_ENUMERATOR (g_task_get_source_object (task));
+
+  G_LOCK (infos);
+  if (enumerator->done || g_list_length (enumerator->infos) >= enumerator->async_requested_files)
+    trigger_async_done (task, TRUE);
+  G_UNLOCK (infos);
+}
+
+static void
 async_cancelled (GCancellable *cancellable,
-                GDaemonFileEnumerator *daemon)
+                 GTask *task)
 {
-  g_simple_async_result_set_error (daemon->async_res,
-                                  G_IO_ERROR,
-                                  G_IO_ERROR_CANCELLED,
-                                  _("Operation was cancelled"));
   G_LOCK (infos);
-  trigger_async_done (daemon, FALSE);
+  trigger_async_done (task, FALSE);
   G_UNLOCK (infos);
 }
 
 static gboolean
-async_timeout (gpointer data)
+async_timeout (GTask *task)
 {
-  GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (data);
-
   G_LOCK (infos);
-  trigger_async_done (daemon, TRUE);
+  trigger_async_done (task, TRUE);
   G_UNLOCK (infos);
   return FALSE;
 }
@@ -576,6 +598,11 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator     *enumerator,
                                           gpointer             user_data)
 {
   GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator);
+  GTask *task;
+
+  task = g_task_new (enumerator, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_daemon_file_enumerator_next_files_async);
+  g_task_set_priority (task, io_priority);
 
   if (daemon->sync_connection != NULL)
     {
@@ -585,34 +612,30 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator     *enumerator,
        * We could possibly pump it ourselves in this case, but i'm not sure
        * how much sense this makes, so we don't for now.
        */
-      g_simple_async_report_error_in_idle  (G_OBJECT (enumerator),
-                                           callback,
-                                           user_data,
-                                           G_IO_ERROR, G_IO_ERROR_FAILED,
-                                           "Can't do asynchronous next_files() on a file enumerator created 
synchronously");
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
+                               "Can't do asynchronous next_files() on a file enumerator created 
synchronously");
+      g_object_unref (task);
       return;
     }
-  
+
   G_LOCK (infos);
   daemon->cancelled_tag = 0;
   daemon->timeout_tag = 0;
   daemon->async_requested_files = num_files;
-  daemon->async_res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data,
-                                                g_daemon_file_enumerator_next_files_async);
-  simple_async_result_set_cancellable (daemon->async_res, cancellable);
 
   /* Maybe we already have enough info to fulfill the requeust already */
   if (daemon->done ||
       g_list_length (daemon->infos) >= daemon->async_requested_files)
-    trigger_async_done (daemon, TRUE);
+    trigger_async_done (task, TRUE);
   else
     {
       daemon->timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS,
-                                          async_timeout, daemon);
+                                           (GSourceFunc) async_timeout, task);
       if (cancellable)
-       daemon->cancelled_tag =
-         g_cancellable_connect (cancellable, (GCallback)async_cancelled,
-                                daemon, NULL);
+        daemon->cancelled_tag =
+          g_cancellable_connect (cancellable, (GCallback) async_cancelled, task, NULL);
+
+      g_signal_connect_swapped (daemon, "changed", G_CALLBACK (async_changed), task);
     }
   
   G_UNLOCK (infos);
@@ -623,23 +646,10 @@ g_daemon_file_enumerator_next_files_finish (GFileEnumerator  *enumerator,
                                            GAsyncResult     *res,
                                            GError          **error)
 {
-  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res);
-  GCancellable *cancellable;
-  GList *l;
-
-  cancellable = simple_async_result_get_cancellable (result);
-  if (g_cancellable_is_cancelled (cancellable))
-    {
-      g_set_error (error,
-                   G_IO_ERROR,
-                   G_IO_ERROR_CANCELLED,
-                   "%s", _("Operation was cancelled"));
-      return NULL;
-    }
+  g_return_val_if_fail (g_task_is_valid (res, enumerator), NULL);
+  g_return_val_if_fail (g_async_result_is_tagged (res, g_daemon_file_enumerator_next_files_async), NULL);
 
-  l = g_simple_async_result_get_op_res_gpointer (result);
-  g_list_foreach (l, (GFunc)g_object_ref, NULL);
-  return g_list_copy (l);
+  return g_task_propagate_pointer (G_TASK (res), error);
 }
 
 static gboolean
@@ -662,13 +672,12 @@ g_daemon_file_enumerator_close_async (GFileEnumerator      *enumerator,
                                      GAsyncReadyCallback   callback,
                                      gpointer              user_data)
 {
-  GSimpleAsyncResult *res;
+  GTask *task;
 
-  res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data,
-                                  g_daemon_file_enumerator_close_async);
-  simple_async_result_set_cancellable (res, cancellable);
-  g_simple_async_result_complete_in_idle (res);
-  g_object_unref (res);
+  task = g_task_new (enumerator, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_daemon_file_enumerator_close_async);
+  g_task_return_boolean (task, TRUE);
+  g_object_unref (task);
 }
 
 static gboolean
@@ -676,17 +685,8 @@ g_daemon_file_enumerator_close_finish (GFileEnumerator      *enumerator,
                                       GAsyncResult         *result,
                                       GError              **error)
 {
-  GCancellable *cancellable;
-  
-  cancellable = simple_async_result_get_cancellable (G_SIMPLE_ASYNC_RESULT (result));
-  if (g_cancellable_is_cancelled (cancellable))
-    {
-      g_set_error (error,
-                   G_IO_ERROR,
-                   G_IO_ERROR_CANCELLED,
-                   "%s", _("Operation was cancelled"));
-      return FALSE;
-    }
+  g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE);
+  g_return_val_if_fail (g_async_result_is_tagged (result, g_daemon_file_enumerator_close_async), FALSE);
 
-  return TRUE;
+  return g_task_propagate_boolean (G_TASK (result), error);
 }


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