[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