[Spice-devel] [spice-gtk v2 03/16] file-xfer: introduce create_tasks and start_task

Victor Toso victortoso at redhat.com
Mon May 23 11:50:40 UTC 2016


By splitting file_xfer_send_start_msg_async we can separate in three
different steps the spice_main_file_copy_async function:

1-) Creating tasks with spice_file_transfer_task_create_tasks which
    now returns a GList of SpiceFileTransferTask;
2-) Setting handlers before the SpiceFileTransferTask starts;
3-) Starting the task with spice_file_transfer_task_start_task

(1) and (3) can be done outside channel-main scope.

This change is related to split SpiceFileTransferTask from
channel-main.
---
 src/channel-main.c | 153 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 90 insertions(+), 63 deletions(-)

diff --git a/src/channel-main.c b/src/channel-main.c
index f4e8c2b..0b355ba 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -86,6 +86,17 @@ typedef void (*SpiceFileTransferTaskFlushCb)(SpiceFileTransferTask *xfer_task,
 static SpiceMainChannel *spice_file_transfer_task_get_channel(SpiceFileTransferTask *self);
 static GCancellable *spice_file_transfer_task_get_cancellable(SpiceFileTransferTask *self);
 static void spice_file_transfer_task_flush_done(SpiceFileTransferTask *self, GError *error);
+static GList *spice_file_transfer_task_create_tasks(SpiceMainChannel *channel,
+                                                    GFile **files,
+                                                    GFileCopyFlags flags,
+                                                    GCancellable *cancellable,
+                                                    GFileProgressCallback progress_callback,
+                                                    gpointer progress_callback_data,
+                                                    SpiceFileTransferTaskFlushCb flush_callback,
+                                                    gpointer flush_callback_data,
+                                                    GAsyncReadyCallback callback,
+                                                    gpointer user_data);
+static void spice_file_transfer_task_start_task(SpiceFileTransferTask *self);
 
 struct _SpiceFileTransferTaskPrivate
 
@@ -3061,60 +3072,10 @@ static void task_finished(SpiceFileTransferTask *task,
                           gpointer data)
 {
     SpiceMainChannel *channel = SPICE_MAIN_CHANNEL(data);
-    g_hash_table_remove(channel->priv->file_xfer_tasks, GUINT_TO_POINTER(task->priv->id));
-}
-
-static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
-                                           GFile **files,
-                                           GFileCopyFlags flags,
-                                           GCancellable *cancellable,
-                                           GFileProgressCallback progress_callback,
-                                           gpointer progress_callback_data,
-                                           SpiceFileTransferTaskFlushCb flush_callback,
-                                           gpointer flush_callback_data,
-                                           GAsyncReadyCallback callback,
-                                           gpointer user_data)
-{
-    SpiceMainChannelPrivate *c = channel->priv;
-    SpiceFileTransferTask *task;
-    gint i;
+    guint32 task_id;
 
-    for (i = 0; files[i] != NULL && !g_cancellable_is_cancelled(cancellable); i++) {
-        GCancellable *task_cancellable = cancellable;
-        /* if a cancellable object was not provided for the overall operation,
-         * create a separate object for each file so that they can be cancelled
-         * separately  */
-        if (!task_cancellable)
-            task_cancellable = g_cancellable_new();
-
-        task = spice_file_transfer_task_new(channel, files[i], task_cancellable);
-        task->priv->flags = flags;
-        task->priv->progress_callback = progress_callback;
-        task->priv->progress_callback_data = progress_callback_data;
-        task->priv->flush_callback = flush_callback;
-        task->priv->flush_callback_data = flush_callback_data;
-        task->priv->callback = callback;
-        task->priv->user_data = user_data;
-
-        CHANNEL_DEBUG(channel, "Insert a xfer task:%d to task list",
-                      task->priv->id);
-        g_hash_table_insert(c->file_xfer_tasks,
-                            GUINT_TO_POINTER(task->priv->id),
-                            task);
-        g_signal_connect(task, "finished", G_CALLBACK(task_finished), channel);
-        g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0, task);
-
-        g_file_read_async(files[i],
-                          G_PRIORITY_DEFAULT,
-                          cancellable,
-                          file_xfer_read_async_cb,
-                          g_object_ref(task));
-        task->priv->pending = TRUE;
-
-        /* if we created a per-task cancellable above, free it */
-        if (!cancellable)
-            g_object_unref(task_cancellable);
-    }
+    g_object_get(task, "id", &task_id, NULL);
+    g_hash_table_remove(channel->priv->file_xfer_tasks, GUINT_TO_POINTER(task_id));
 }
 
 /**
@@ -3160,6 +3121,7 @@ void spice_main_file_copy_async(SpiceMainChannel *channel,
                                 gpointer user_data)
 {
     SpiceMainChannelPrivate *c = channel->priv;
+    GList *tasks, *it;
 
     g_return_if_fail(channel != NULL);
     g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
@@ -3176,16 +3138,27 @@ void spice_main_file_copy_async(SpiceMainChannel *channel,
         return;
     }
 
-    file_xfer_send_start_msg_async(channel,
-                                   sources,
-                                   flags,
-                                   cancellable,
-                                   progress_callback,
-                                   progress_callback_data,
-                                   file_xfer_flush_callback,
-                                   NULL,
-                                   callback,
-                                   user_data);
+    tasks = spice_file_transfer_task_create_tasks(channel,
+                                                  sources,
+                                                  flags,
+                                                  cancellable,
+                                                  progress_callback,
+                                                  progress_callback_data,
+                                                  file_xfer_flush_callback,
+                                                  NULL,
+                                                  callback,
+                                                  user_data);
+    for (it = tasks; it != NULL; it = it->next) {
+        SpiceFileTransferTask *task = SPICE_FILE_TRANSFER_TASK(it->data);
+        guint32 task_id;
+
+        g_object_get(task, "id", &task_id, NULL);
+        g_hash_table_insert(c->file_xfer_tasks, GUINT_TO_POINTER(task_id), task);
+        g_signal_connect(task, "finished", G_CALLBACK(task_finished), channel);
+        g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0, task);
+        spice_file_transfer_task_start_task(task);
+    }
+    g_list_free(tasks);
 }
 
 /**
@@ -3272,6 +3245,60 @@ static void spice_file_transfer_task_flush_done(SpiceFileTransferTask *self, GEr
     file_xfer_continue_read(self);
 }
 
+static GList *spice_file_transfer_task_create_tasks(SpiceMainChannel *channel,
+                                                    GFile **files,
+                                                    GFileCopyFlags flags,
+                                                    GCancellable *cancellable,
+                                                    GFileProgressCallback progress_callback,
+                                                    gpointer progress_callback_data,
+                                                    SpiceFileTransferTaskFlushCb flush_callback,
+                                                    gpointer flush_callback_data,
+                                                    GAsyncReadyCallback callback,
+                                                    gpointer user_data)
+{
+    SpiceFileTransferTask *task;
+    gint i;
+    GList *tasks = NULL;
+
+    for (i = 0; files[i] != NULL && !g_cancellable_is_cancelled(cancellable); i++) {
+        GCancellable *task_cancellable = cancellable;
+        /* if a cancellable object was not provided for the overall operation,
+         * create a separate object for each file so that they can be cancelled
+         * separately  */
+        if (!task_cancellable)
+            task_cancellable = g_cancellable_new();
+
+        task = spice_file_transfer_task_new(channel, files[i], task_cancellable);
+        task->priv->flags = flags;
+        task->priv->progress_callback = progress_callback;
+        task->priv->progress_callback_data = progress_callback_data;
+        task->priv->flush_callback = flush_callback;
+        task->priv->flush_callback_data = flush_callback_data;
+        task->priv->callback = callback;
+        task->priv->user_data = user_data;
+
+        CHANNEL_DEBUG(channel, "Insert a xfer task:%d to task list",
+                      task->priv->id);
+        tasks = g_list_prepend(tasks, task);
+
+        /* if we created a per-task cancellable above, free it */
+        if (!cancellable)
+            g_object_unref(task_cancellable);
+    }
+
+    return g_list_reverse(tasks);
+}
+
+static void spice_file_transfer_task_start_task(SpiceFileTransferTask *self)
+{
+    g_assert_nonnull(self);
+    self->priv->pending = TRUE;
+    g_file_read_async(self->priv->file,
+                      G_PRIORITY_DEFAULT,
+                      self->priv->cancellable,
+                      file_xfer_read_async_cb,
+                      g_object_ref(self));
+}
 
 static void
 spice_file_transfer_task_get_property(GObject *object,
-- 
2.5.5



More information about the Spice-devel mailing list