diff options
author | Debarshi Ray <debarshir@src.gnome.org> | 2011-09-07 11:00:27 +0300 |
---|---|---|
committer | Debarshi Ray <debarshir@src.gnome.org> | 2011-09-08 22:59:42 +0300 |
commit | 5fb6ef3d1570b58d1f0446001a7544ecdecd8a75 (patch) | |
tree | c2c06997f47c751da768f0be8860394c957f221a | |
parent | 5e987ff6c3c0cb8e110dc8cf1d07674adc8e2ec7 (diff) | |
download | gusb-5fb6ef3d1570b58d1f0446001a7544ecdecd8a75.tar.gz |
Ensure that there is only one GUsbSource for each GUsbContext
As a result, g_usb_source_{new,destroy} have been moved to a private
header, and are called from the get_source and finalize methods of
GUsbContext.
Note that the GUsbSource is lazy allocated and only created when
g_usb_context_get_source is called for the first time for a particular
GUsbContext.
-rw-r--r-- | gusb/Makefile.am | 1 | ||||
-rw-r--r-- | gusb/gusb-context.c | 41 | ||||
-rw-r--r-- | gusb/gusb-context.h | 4 | ||||
-rw-r--r-- | gusb/gusb-device.c | 12 | ||||
-rw-r--r-- | gusb/gusb-private.h | 1 | ||||
-rw-r--r-- | gusb/gusb-self-test.c | 6 | ||||
-rw-r--r-- | gusb/gusb-source-private.h | 35 | ||||
-rw-r--r-- | gusb/gusb-source.c | 16 | ||||
-rw-r--r-- | gusb/gusb-source.h | 6 |
9 files changed, 93 insertions, 29 deletions
diff --git a/gusb/Makefile.am b/gusb/Makefile.am index e2690b0..2d4999a 100644 --- a/gusb/Makefile.am +++ b/gusb/Makefile.am @@ -26,6 +26,7 @@ libgusbbase_include_HEADERS = \ gusb-device-private.h \ gusb-device-list.h \ gusb-source.h \ + gusb-source-private.h \ gusb-util.h libgusb_la_SOURCES = \ diff --git a/gusb/gusb-context.c b/gusb/gusb-context.c index 2abd5b4..cccd8ff 100644 --- a/gusb/gusb-context.c +++ b/gusb/gusb-context.c @@ -33,6 +33,7 @@ #include "gusb-util.h" #include "gusb-context.h" #include "gusb-context-private.h" +#include "gusb-source-private.h" static void g_usb_context_finalize (GObject *object); @@ -51,6 +52,8 @@ enum { **/ struct _GUsbContextPrivate { + GStaticMutex source_mutex; + GUsbSource *source; libusb_context *context; int debug_level; }; @@ -179,7 +182,11 @@ g_usb_context_class_init (GUsbContextClass *klass) static void g_usb_context_init (GUsbContext *context) { - context->priv = G_USB_CONTEXT_GET_PRIVATE (context); + GUsbContextPrivate *priv; + + priv = context->priv = G_USB_CONTEXT_GET_PRIVATE (context); + g_static_mutex_init (&priv->source_mutex); + priv->source = NULL; } /** @@ -191,6 +198,10 @@ g_usb_context_finalize (GObject *object) GUsbContext *context = G_USB_CONTEXT (object); GUsbContextPrivate *priv = context->priv; + g_static_mutex_free (&priv->source_mutex); + if (priv->source != NULL) + _g_usb_source_destroy (priv->source); + libusb_exit (priv->context); G_OBJECT_CLASS (g_usb_context_parent_class)->finalize (object); @@ -229,6 +240,34 @@ _g_usb_context_get_context (GUsbContext *context) } /** + * g_usb_context_get_source: + * @context: a #GUsbContext + * @main_ctx: a #GMainContext, or %NULL + * + * Returns a source for this context. The first call actually creates + * the source and the result is returned in all future calls. + * + * Return value: (transfer none): the #GUsbSource. + * + * Since: 0.1.0 + **/ +GUsbSource * +g_usb_context_get_source (GUsbContext *context, + GMainContext *main_ctx) +{ + GUsbContextPrivate *priv = context->priv; + + if (priv->source == NULL) { + g_static_mutex_lock (&priv->source_mutex); + if (priv->source == NULL) + priv->source = _g_usb_source_new (main_ctx, context); + g_static_mutex_unlock (&priv->source_mutex); + } + + return priv->source; +} + +/** * g_usb_context_set_debug: * @context: a #GUsbContext * @flags: a GLogLevelFlags such as %G_LOG_LEVEL_ERROR | %G_LOG_LEVEL_INFO, or 0 diff --git a/gusb/gusb-context.h b/gusb/gusb-context.h index 6387bfb..5a6ad46 100644 --- a/gusb/gusb-context.h +++ b/gusb/gusb-context.h @@ -23,6 +23,7 @@ #define __GUSB_CONTEXT_H__ #include <glib-object.h> +#include <gusb/gusb-source.h> #include <gusb/gusb-util.h> G_BEGIN_DECLS @@ -62,6 +63,9 @@ GQuark g_usb_context_error_quark (void); GUsbContext *g_usb_context_new (GError **error); +GUsbSource *g_usb_context_get_source (GUsbContext *context, + GMainContext *main_ctx); + void g_usb_context_set_debug (GUsbContext *context, GLogLevelFlags flags); diff --git a/gusb/gusb-device.c b/gusb/gusb-device.c index 6d73661..4071018 100644 --- a/gusb/gusb-device.c +++ b/gusb/gusb-device.c @@ -34,7 +34,6 @@ #include <libusb-1.0/libusb.h> #include "gusb-context.h" -#include "gusb-source.h" #include "gusb-util.h" #include "gusb-device.h" #include "gusb-device-private.h" @@ -601,7 +600,6 @@ g_usb_device_interrupt_transfer (GUsbDevice *device, typedef struct { GCancellable *cancellable; gulong cancellable_id; - GUsbSource *source; struct libusb_transfer *transfer; GSimpleAsyncResult *res; guint8 *data; /* owned by the user */ @@ -616,7 +614,6 @@ g_usb_device_req_free (GcmDeviceReq *req) g_object_unref (req->cancellable); } - g_usb_source_destroy (req->source); libusb_free_transfer (req->transfer); g_object_unref (req->res); g_slice_free (GcmDeviceReq, req); @@ -857,8 +854,7 @@ g_usb_device_control_transfer_async (GUsbDevice *device, } /* setup with the default mainloop */ - req->source = g_usb_source_new (NULL, - device->priv->context); + g_usb_context_get_source (device->priv->context, NULL); } /**********************************************************************/ @@ -971,8 +967,7 @@ g_usb_device_bulk_transfer_async (GUsbDevice *device, } /* setup with the default mainloop */ - req->source = g_usb_source_new (NULL, - device->priv->context); + g_usb_context_get_source (device->priv->context, NULL); } /**********************************************************************/ @@ -1085,8 +1080,7 @@ g_usb_device_interrupt_transfer_async (GUsbDevice *device, } /* setup with the default mainloop */ - req->source = g_usb_source_new (NULL, - device->priv->context); + g_usb_context_get_source (device->priv->context, NULL); } /**********************************************************************/ diff --git a/gusb/gusb-private.h b/gusb/gusb-private.h index dc3607e..fa67cd1 100644 --- a/gusb/gusb-private.h +++ b/gusb/gusb-private.h @@ -27,6 +27,7 @@ #include <gusb/gusb.h> #include <gusb/gusb-context-private.h> #include <gusb/gusb-device-private.h> +#include <gusb/gusb-source-private.h> #undef __GUSB_INSIDE__ diff --git a/gusb/gusb-self-test.c b/gusb/gusb-self-test.c index 26d0e95..df37039 100644 --- a/gusb/gusb-self-test.c +++ b/gusb/gusb-self-test.c @@ -24,7 +24,6 @@ #include <glib-object.h> #include "gusb-context.h" -#include "gusb-source.h" #include "gusb-device.h" #include "gusb-device-list.h" @@ -54,12 +53,11 @@ gusb_source_func (void) g_assert_no_error (error); g_assert (ctx != NULL); - source = g_usb_source_new (NULL, ctx); - g_assert (ctx != NULL); + source = g_usb_context_get_source (ctx, NULL); + g_assert (source != NULL); /* TODO: test callback? */ - g_usb_source_destroy (source); g_object_unref (ctx); } diff --git a/gusb/gusb-source-private.h b/gusb/gusb-source-private.h new file mode 100644 index 0000000..a7509de --- /dev/null +++ b/gusb/gusb-source-private.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2011 Debarshi Ray <debarshir@src.gnome.org> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GUSB_SOURCE_PRIVATE_H__ +#define __GUSB_SOURCE_PRIVATE_H__ + +#include <gusb/gusb-context.h> +#include <gusb/gusb-source.h> + +G_BEGIN_DECLS + +GUsbSource *_g_usb_source_new (GMainContext *main_ctx, + GUsbContext *context); +void _g_usb_source_destroy (GUsbSource *source); + +G_END_DECLS + +#endif /* __GUSB_SOURCE_PRIVATE_H__ */ diff --git a/gusb/gusb-source.c b/gusb/gusb-source.c index ddb4635..c9c931f 100644 --- a/gusb/gusb-source.c +++ b/gusb/gusb-source.c @@ -37,6 +37,7 @@ #include "gusb-context-private.h" #include "gusb-util.h" #include "gusb-source.h" +#include "gusb-source-private.h" /** * g_usb_source_error_quark: @@ -57,7 +58,6 @@ g_usb_source_error_quark (void) struct _GUsbSource { GSource source; GSList *pollfds; - GUsbContext *usbcontext; libusb_context *ctx; }; @@ -208,7 +208,6 @@ static void g_usb_source_finalize (GSource *source) { GUsbSource *usb_source = (GUsbSource *)source; - g_object_unref (usb_source->usbcontext); g_slist_free (usb_source->pollfds); } @@ -221,20 +220,20 @@ static GSourceFuncs usb_source_funcs = { }; /** - * g_usb_source_new: + * _g_usb_source_new: * @main_ctx: a #GMainContext, or %NULL * @gusb_ctx: a #GUsbContext * @error: a #GError, or %NULL * * Creates a source for integration into libusb1. * - * Return value: (transfer none): the #GUsbSource. Use g_usb_source_destroy() to unref. + * Return value: (transfer none): the #GUsbSource. Use _g_usb_source_destroy() to unref. * * Since: 0.1.0 **/ GUsbSource * -g_usb_source_new (GMainContext *main_ctx, - GUsbContext *gusb_ctx) +_g_usb_source_new (GMainContext *main_ctx, + GUsbContext *gusb_ctx) { guint i; const struct libusb_pollfd **pollfds; @@ -243,7 +242,6 @@ g_usb_source_new (GMainContext *main_ctx, gusb_source = (GUsbSource *)g_source_new (&usb_source_funcs, sizeof(GUsbSource)); gusb_source->pollfds = NULL; - gusb_source->usbcontext = g_object_ref (gusb_ctx); gusb_source->ctx = _g_usb_context_get_context (gusb_ctx); /* watch the fd's already created */ @@ -265,7 +263,7 @@ g_usb_source_new (GMainContext *main_ctx, } /** - * g_usb_source_destroy: + * _g_usb_source_destroy: * @source: a #GUsbSource * * Destroys a #GUsbSource @@ -273,7 +271,7 @@ g_usb_source_new (GMainContext *main_ctx, * Since: 0.1.0 **/ void -g_usb_source_destroy (GUsbSource *source) +_g_usb_source_destroy (GUsbSource *source) { libusb_set_pollfd_notifiers (source->ctx, NULL, NULL, NULL); g_usb_source_pollfd_remove_all (source); diff --git a/gusb/gusb-source.h b/gusb/gusb-source.h index b840c67..909659e 100644 --- a/gusb/gusb-source.h +++ b/gusb/gusb-source.h @@ -25,8 +25,6 @@ #include <glib.h> -#include <gusb/gusb-context.h> - G_BEGIN_DECLS #define G_USB_SOURCE_ERROR (g_usb_source_error_quark ()) @@ -43,10 +41,6 @@ typedef enum { } GUsbSourceError; GQuark g_usb_source_error_quark (void); -GUsbSource *g_usb_source_new (GMainContext *main_ctx, - GUsbContext *gusb_ctx); -void g_usb_source_destroy (GUsbSource *source); - void g_usb_source_set_callback (GUsbSource *source, GSourceFunc func, gpointer data, |