summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDebarshi Ray <debarshir@src.gnome.org>2011-09-07 11:00:27 +0300
committerDebarshi Ray <debarshir@src.gnome.org>2011-09-08 22:59:42 +0300
commit5fb6ef3d1570b58d1f0446001a7544ecdecd8a75 (patch)
treec2c06997f47c751da768f0be8860394c957f221a
parent5e987ff6c3c0cb8e110dc8cf1d07674adc8e2ec7 (diff)
downloadgusb-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.am1
-rw-r--r--gusb/gusb-context.c41
-rw-r--r--gusb/gusb-context.h4
-rw-r--r--gusb/gusb-device.c12
-rw-r--r--gusb/gusb-private.h1
-rw-r--r--gusb/gusb-self-test.c6
-rw-r--r--gusb/gusb-source-private.h35
-rw-r--r--gusb/gusb-source.c16
-rw-r--r--gusb/gusb-source.h6
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,