ack On Wed, Nov 16, 2011 at 6:49 PM, Hans de Goede <hdego...@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 <hdego...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/spice-devel >
-- Marc-André Lureau _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel