[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