[Spice-devel] [PATCH 11/14] vmcstream: Use GTask instead of GSimpleAsyncResult
Christophe Fergeau
cfergeau at redhat.com
Mon Jan 18 08:54:00 PST 2016
On Mon, Jan 18, 2016 at 10:05:47AM +0100, Fabiano FidĂȘncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
> src/vmcstream.c | 129 +++++++++++++++++++++++---------------------------------
> 1 file changed, 52 insertions(+), 77 deletions(-)
>
> diff --git a/src/vmcstream.c b/src/vmcstream.c
> index 483dd5a..d9b62a0 100644
> --- a/src/vmcstream.c
> +++ b/src/vmcstream.c
> @@ -27,7 +27,7 @@
> struct _SpiceVmcInputStream
> {
> GInputStream parent_instance;
> - GSimpleAsyncResult *result;
> + GTask *task;
> struct coroutine *coroutine;
>
> SpiceChannel *channel;
> @@ -36,7 +36,6 @@ struct _SpiceVmcInputStream
> gsize count;
> gsize pos;
>
> - GCancellable *cancellable;
> gulong cancel_id;
> };
>
> @@ -118,11 +117,12 @@ spice_vmc_input_stream_co_data(SpiceVmcInputStream *self,
> self->coroutine = coroutine_self();
>
> while (size > 0) {
> - SPICE_DEBUG("spicevmc co_data %p", self->result);
> - if (!self->result)
> + GCancellable *cancellable;
> + SPICE_DEBUG("spicevmc co_data %p", self->task);
> + if (!self->task)
> coroutine_yield(NULL);
>
> - g_return_if_fail(self->result != NULL);
> + g_return_if_fail(self->task != NULL);
>
> gsize min = MIN(self->count, size);
> memcpy(self->buffer, data, min);
> @@ -139,14 +139,13 @@ spice_vmc_input_stream_co_data(SpiceVmcInputStream *self,
> if (self->all && min > 0 && self->pos != self->count)
> continue;
>
> - g_simple_async_result_set_op_res_gssize(self->result, self->pos);
> + g_task_return_int(self->task, self->pos);
> +
> + cancellable = g_task_get_cancellable(self->task);
> + if (cancellable)
> + g_cancellable_disconnect(cancellable, self->cancel_id);
>
> - g_simple_async_result_complete_in_idle(self->result);
> - g_clear_object(&self->result);
> - if (self->cancellable) {
> - g_cancellable_disconnect(self->cancellable, self->cancel_id);
> - g_clear_object(&self->cancellable);
> - }
> + g_clear_object(&self->task);
> }
>
> self->coroutine = NULL;
> @@ -158,13 +157,12 @@ read_cancelled(GCancellable *cancellable,
> {
> SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(user_data);
>
> - SPICE_DEBUG("read cancelled, %p", self->result);
> - g_simple_async_result_set_error(self->result,
> - G_IO_ERROR, G_IO_ERROR_CANCELLED,
> - "read cancelled");
> - g_simple_async_result_complete_in_idle(self->result);
> + SPICE_DEBUG("read cancelled, %p", self->task);
> + g_task_return_new_error(self->task,
> + G_IO_ERROR, G_IO_ERROR_CANCELLED,
> + "read cancelled");
>
> - g_clear_object(&self->result);
> + g_clear_object(&self->task);
>
> /* See FIXME */
> /* if (self->cancellable) { */
> @@ -183,21 +181,20 @@ spice_vmc_input_stream_read_all_async(GInputStream *stream,
> gpointer user_data)
> {
> SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
> - GSimpleAsyncResult *result;
> + GTask *task;
>
> /* no concurrent read permitted by ginputstream */
> - g_return_if_fail(self->result == NULL);
> - g_return_if_fail(self->cancellable == NULL);
> + g_return_if_fail(self->task == NULL);
> + g_return_if_fail(g_task_get_cancellable(self->task) == NULL);
> self->all = TRUE;
> self->buffer = buffer;
> self->count = count;
> self->pos = 0;
> - result = g_simple_async_result_new(G_OBJECT(self),
> - callback,
> - user_data,
> - spice_vmc_input_stream_read_async);
> - self->result = result;
> - self->cancellable = g_object_ref(cancellable);
> + task = g_task_new(self,
> + cancellable,
> + callback,
> + user_data);
> + self->task = task;
> if (cancellable)
> self->cancel_id =
> g_cancellable_connect(cancellable, G_CALLBACK(read_cancelled), self, NULL);
> @@ -211,27 +208,19 @@ spice_vmc_input_stream_read_all_finish(GInputStream *stream,
> GAsyncResult *result,
> GError **error)
> {
> - GSimpleAsyncResult *simple;
> + GTask *task = G_TASK(result);
> + GCancellable *cancellable;
> SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
>
> - g_return_val_if_fail(g_simple_async_result_is_valid(result,
> - G_OBJECT(self),
> - spice_vmc_input_stream_read_async),
> - -1);
> -
> - simple = (GSimpleAsyncResult *)result;
> + g_return_val_if_fail(g_task_is_valid(task, self), -1);
>
> /* FIXME: calling _finish() is required. Disconnecting in
> read_cancelled() causes a deadlock. #705395 */
> - if (self->cancellable) {
> - g_cancellable_disconnect(self->cancellable, self->cancel_id);
> - g_clear_object(&self->cancellable);
> - }
> -
> - if (g_simple_async_result_propagate_error(simple, error))
> - return -1;
> + cancellable = g_task_get_cancellable(task);
> + if (cancellable)
> + g_cancellable_disconnect(cancellable, self->cancel_id);
>
> - return g_simple_async_result_get_op_res_gssize(simple);
> + return g_task_propagate_int(task, error);
> }
>
> static void
> @@ -244,21 +233,18 @@ spice_vmc_input_stream_read_async(GInputStream *stream,
> gpointer user_data)
> {
> SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
> - GSimpleAsyncResult *result;
> + GTask *task;
>
> /* no concurrent read permitted by ginputstream */
> - g_return_if_fail(self->result == NULL);
> - g_return_if_fail(self->cancellable == NULL);
> + g_return_if_fail(self->task == NULL);
> + g_return_if_fail(g_task_get_cancellable(self->task) == NULL);
> self->all = FALSE;
> self->buffer = buffer;
> self->count = count;
> self->pos = 0;
> - result = g_simple_async_result_new(G_OBJECT(self),
> - callback,
> - user_data,
> - spice_vmc_input_stream_read_async);
> - self->result = result;
> - self->cancellable = g_object_ref(cancellable);
> +
> + task = g_task_new(self, cancellable, callback, user_data);
> + self->task = task;
> if (cancellable)
> self->cancel_id =
> g_cancellable_connect(cancellable, G_CALLBACK(read_cancelled), self, NULL);
> @@ -272,27 +258,19 @@ spice_vmc_input_stream_read_finish(GInputStream *stream,
> GAsyncResult *result,
> GError **error)
> {
> - GSimpleAsyncResult *simple;
> + GTask *task = G_TASK(result);
> + GCancellable *cancellable;
> SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
>
> - g_return_val_if_fail(g_simple_async_result_is_valid(result,
> - G_OBJECT(self),
> - spice_vmc_input_stream_read_async),
> - -1);
> -
> - simple = (GSimpleAsyncResult *)result;
> + g_return_val_if_fail(g_task_is_valid(task, self), -1);
>
> /* FIXME: calling _finish() is required. Disconnecting in
> read_cancelled() causes a deadlock. #705395 */
> - if (self->cancellable) {
> - g_cancellable_disconnect(self->cancellable, self->cancel_id);
> - g_clear_object(&self->cancellable);
> - }
> -
> - if (g_simple_async_result_propagate_error(simple, error))
> - return -1;
> + cancellable = g_task_get_cancellable(task);
> + if (cancellable)
> + g_cancellable_disconnect(cancellable, self->cancel_id);
>
> - return g_simple_async_result_get_op_res_gssize(simple);
> + return g_task_propagate_int(task, error);
> }
>
> static gssize
> @@ -407,11 +385,10 @@ spice_vmc_output_stream_write_finish(GOutputStream *stream,
> GError **error)
> {
> SpiceVmcOutputStream *self = SPICE_VMC_OUTPUT_STREAM(stream);
> - GSimpleAsyncResult *res =
> - g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(simple));
> + GAsyncResult *res = g_task_propagate_pointer(G_TASK(simple), error);
>
> SPICE_DEBUG("spicevmc write finish");
> - return spice_vmc_write_finish(self->channel, G_ASYNC_RESULT(res), error);
> + return spice_vmc_write_finish(self->channel, res, error);
> }
>
> static void
> @@ -419,12 +396,11 @@ write_cb(GObject *source_object,
> GAsyncResult *res,
> gpointer user_data)
> {
> - GSimpleAsyncResult *simple = user_data;
> + GTask *task = user_data;
>
> - g_simple_async_result_set_op_res_gpointer(simple, res, NULL);
> + g_task_return_pointer(task, res, NULL);
>
> - g_simple_async_result_complete(simple);
> - g_object_unref(simple);
> + g_object_unref(task);
As we have less control with GTask over whether g_task_return_pointer
will call the callback immediatly or queue an idle, I'm wondering
whether we should g_object_ref(res) in g_task_return_pointer() to be
sure it's still alive in case we run in an idle (though more things may
break if an idle is involved rather than a direct call).
Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20160118/14467a95/attachment.sig>
More information about the Spice-devel
mailing list