[Spice-devel] [PATCH spice-gtk 3/5] channel-usbredir.c: Make spice_usbredir_channel_connect async

Marc-André Lureau marcandre.lureau at gmail.com
Tue Nov 15 11:38:24 PST 2011


ack

On Tue, Nov 15, 2011 at 4:30 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 |   13 ++++++++---
>  gtk/channel-usbredir.c      |   49 ++++++++++++++++++++++++++++++++++++-------
>  gtk/usb-device-manager.c    |   29 +++++++++++++++++++------
>  3 files changed, 72 insertions(+), 19 deletions(-)
>
> diff --git a/gtk/channel-usbredir-priv.h b/gtk/channel-usbredir-priv.h
> index 05988e1..700bad2 100644
> --- a/gtk/channel-usbredir-priv.h
> +++ b/gtk/channel-usbredir-priv.h
> @@ -28,10 +28,15 @@
>
>  G_BEGIN_DECLS
>
> -gboolean spice_usbredir_channel_connect(SpiceUsbredirChannel *channel,
> -                                        GUsbContext *context,
> -                                        GUsbDevice *device,
> -                                        GError **err);
> +void spice_usbredir_channel_connect(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 474ffb5..94c801a 100644
> --- a/gtk/channel-usbredir.c
> +++ b/gtk/channel-usbredir.c
> @@ -150,27 +150,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(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_usbredir_channel_disconnect(channel);
> +    result = g_simple_async_result_new(G_OBJECT(channel), callback, user_data,
> +                                       spice_usbredir_channel_connect);
> +
> +    if (priv->device) {
> +        g_simple_async_result_set_error(result,
> +                            SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> +                            "Cannot connect an already connected usb channel");
> +        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),
> +                         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 dd2e0c4..7f1cc12 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(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(channel,
> +                                 priv->context,
> +                                 (GUsbDevice *)device,
> +                                 cancellable,
> +                                 spice_usb_device_manager_channel_connect_cb,
> +                                 result);
> +        return;
>     }
>  #endif
>
> --
> 1.7.7.1
>
> _______________________________________________
> 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