[Spice-devel] [PATCH spice-gtk 6/8] channel-usbredir: Make spice_usbredir_channel_connect async
Hans de Goede
hdegoede at redhat.com
Wed Nov 16 09:49:49 PST 2011
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
More information about the Spice-devel
mailing list