[Spice-devel] [PATCH spice-gtk 6/8] channel-usbredir: Make spice_usbredir_channel_connect async
Marc-André Lureau
marcandre.lureau at gmail.com
Sun Nov 20 14:35:23 PST 2011
ack
On Wed, Nov 16, 2011 at 6:49 PM, Hans de Goede <hdegoede at redhat.com> wrote:
> With the (upcoming) introduction of the usb device node acl helper, which
> uses policykit, spice_usbredir_channel_connect() may take a long time as
> it will be waiting for the helper, which will be waiting for policykit which
> may be interacting with the user -> Make spice_usbredir_channel_connect() async
>
> Note that this patch only changes spice_usbredir_channel_connect's
> API to use the standard GIO async API, it is not actually async after this
> patch since it does not yet call the acl helper.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
> gtk/channel-usbredir-priv.h | 14 ++++++++---
> gtk/channel-usbredir.c | 49 ++++++++++++++++++++++++++++++++++++-------
> gtk/usb-device-manager.c | 29 +++++++++++++++++++------
> 3 files changed, 73 insertions(+), 19 deletions(-)
>
> diff --git a/gtk/channel-usbredir-priv.h b/gtk/channel-usbredir-priv.h
> index 05988e1..8bb42a5 100644
> --- a/gtk/channel-usbredir-priv.h
> +++ b/gtk/channel-usbredir-priv.h
> @@ -28,10 +28,16 @@
>
> G_BEGIN_DECLS
>
> -gboolean spice_usbredir_channel_connect(SpiceUsbredirChannel *channel,
> - GUsbContext *context,
> - GUsbDevice *device,
> - GError **err);
> +void spice_usbredir_channel_connect_async(SpiceUsbredirChannel *channel,
> + GUsbContext *context,
> + GUsbDevice *device,
> + GCancellable *cancellable,
> + GAsyncReadyCallback callback,
> + gpointer user_data);
> +gboolean spice_usbredir_channel_connect_finish(SpiceUsbredirChannel *channel,
> + GAsyncResult *res,
> + GError **err);
> +
> void spice_usbredir_channel_disconnect(SpiceUsbredirChannel *channel);
>
> GUsbDevice *spice_usbredir_channel_get_device(SpiceUsbredirChannel *channel);
> diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
> index 4194b48..fd54594 100644
> --- a/gtk/channel-usbredir.c
> +++ b/gtk/channel-usbredir.c
> @@ -153,27 +153,60 @@ static gboolean spice_usbredir_channel_open_device(
> }
>
> G_GNUC_INTERNAL
> -gboolean spice_usbredir_channel_connect(SpiceUsbredirChannel *channel,
> - GUsbContext *context,
> - GUsbDevice *device,
> - GError **err)
> +void spice_usbredir_channel_connect_async(SpiceUsbredirChannel *channel,
> + GUsbContext *context,
> + GUsbDevice *device,
> + GCancellable *cancellable,
> + GAsyncReadyCallback callback,
> + gpointer user_data)
> {
> SpiceUsbredirChannelPrivate *priv = channel->priv;
> + GSimpleAsyncResult *result;
> + GError *err = NULL;
>
> - g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
> + g_return_if_fail(SPICE_IS_USBREDIR_CHANNEL(channel));
> + g_return_if_fail(context != NULL);
> + g_return_if_fail(device != NULL);
>
> SPICE_DEBUG("connecting usb channel %p", channel);
>
> - spice_channel_disconnect(SPICE_CHANNEL(channel), SPICE_CHANNEL_NONE);
> + result = g_simple_async_result_new(G_OBJECT(channel), callback, user_data,
> + spice_usbredir_channel_connect_async);
> +
> + if (priv->device) {
> + g_simple_async_result_set_error(result,
> + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> + "Error channel is busy");
> + goto done;
> + }
>
> priv->context = g_object_ref(context);
> priv->device = g_object_ref(device);
> - if (!spice_usbredir_channel_open_device(channel, err)) {
> + if (!spice_usbredir_channel_open_device(channel, &err)) {
> + g_simple_async_result_take_error(result, err);
> g_clear_object(&priv->context);
> g_clear_object(&priv->device);
> - return FALSE;
> }
>
> +done:
> + g_simple_async_result_complete_in_idle(result);
> + g_object_unref(result);
> +}
> +
> +G_GNUC_INTERNAL
> +gboolean spice_usbredir_channel_connect_finish(SpiceUsbredirChannel *channel,
> + GAsyncResult *res,
> + GError **err)
> +{
> + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(res);
> +
> + g_return_val_if_fail(g_simple_async_result_is_valid(res, G_OBJECT(channel),
> + spice_usbredir_channel_connect_async),
> + FALSE);
> +
> + if (g_simple_async_result_propagate_error(result, err))
> + return FALSE;
> +
> return TRUE;
> }
>
> diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
> index 9b02066..b1d6c95 100644
> --- a/gtk/usb-device-manager.c
> +++ b/gtk/usb-device-manager.c
> @@ -480,6 +480,21 @@ static void spice_usb_device_manager_dev_removed(GUsbDeviceList *devlist,
> g_signal_emit(manager, signals[DEVICE_REMOVED], 0, device);
> g_ptr_array_remove(priv->devices, device);
> }
> +
> +static void spice_usb_device_manager_channel_connect_cb(
> + GObject *gobject, GAsyncResult *channel_res, gpointer user_data)
> +{
> + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject);
> + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(user_data);
> + GError *err = NULL;
> +
> + spice_usbredir_channel_connect_finish(channel, channel_res, &err);
> + if (err) {
> + g_simple_async_result_take_error(result, err);
> + }
> + g_simple_async_result_complete(result);
> + g_object_unref(result);
> +}
> #endif
>
> /* ------------------------------------------------------------------ */
> @@ -635,13 +650,13 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
> if (spice_usbredir_channel_get_device(channel))
> continue; /* Skip already used channels */
>
> - if (!spice_usbredir_channel_connect(channel, priv->context,
> - (GUsbDevice *)device, &e)) {
> - g_simple_async_result_take_error(result, e);
> - goto done;
> - }
> -
> - goto done;
> + spice_usbredir_channel_connect_async(channel,
> + priv->context,
> + (GUsbDevice *)device,
> + cancellable,
> + spice_usb_device_manager_channel_connect_cb,
> + result);
> + return;
> }
> #endif
>
> --
> 1.7.7.3
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
>
--
Marc-André Lureau
More information about the Spice-devel
mailing list