[glib] Add g_clear_pointer()
- From: Xavier Claessens <xclaesse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Add g_clear_pointer()
- Date: Fri, 27 Apr 2012 07:43:33 +0000 (UTC)
commit 00285b7517a63a243a5b61b738de5eea957ae767
Author: Xavier Claessens <xavier claessens collabora co uk>
Date: Mon Apr 23 17:57:56 2012 +0200
Add g_clear_pointer()
Also reimplement g_clear_object() using g_clear_pointer()
https://bugzilla.gnome.org/show_bug.cgi?id=674634
docs/reference/glib/glib-sections.txt | 1 +
glib/glib.symbols | 1 +
glib/gmem.c | 39 +++++++++++++++++++++++++++++++++
glib/gmem.h | 18 +++++++++++++++
gobject/gobject.c | 13 +----------
gobject/gobject.h | 14 +-----------
6 files changed, 61 insertions(+), 25 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index ef1b562..141c7bb 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -925,6 +925,7 @@ g_try_realloc_n
<SUBSECTION>
g_free
+g_clear_pointer
g_mem_gc_friendly
<SUBSECTION>
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 6c2db0d..fdafb3e 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -682,6 +682,7 @@ g_markup_printf_escaped
g_markup_vprintf_escaped
g_markup_collect_attributes
g_free
+g_clear_pointer
g_malloc
g_malloc0
g_malloc_n
diff --git a/glib/gmem.c b/glib/gmem.c
index 1f01cd1..3283f2b 100644
--- a/glib/gmem.c
+++ b/glib/gmem.c
@@ -254,6 +254,45 @@ g_free (gpointer mem)
}
/**
+ * g_clear_pointer: (skip)
+ * @pp: a pointer to a variable, struct member etc. holding a pointer
+ * @destroy: a function to which a gpointer can be passed, to destroy * pp
+ *
+ * Clears a reference to a variable.
+ *
+ * @pp must not be %NULL.
+ *
+ * If the reference is %NULL then this function does nothing.
+ * Otherwise, the variable is destroyed using @destroy and the
+ * pointer is set to %NULL.
+ *
+ * This function is threadsafe and modifies the pointer atomically,
+ * using memory barriers where needed.
+ *
+ * A macro is also included that allows this function to be used without
+ * pointer casts.
+ *
+ * Since: 2.34
+ **/
+#undef g_clear_pointer
+void
+g_clear_pointer (gpointer *pp,
+ GDestroyNotify destroy)
+{
+ gpointer _p;
+
+ /* This is a little frustrating.
+ * Would be nice to have an atomic exchange (with no compare).
+ */
+ do
+ _p = g_atomic_pointer_get (pp);
+ while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (pp, _p, NULL));
+
+ if (_p)
+ destroy (_p);
+}
+
+/**
* g_try_malloc:
* @n_bytes: number of bytes to allocate.
*
diff --git a/glib/gmem.h b/glib/gmem.h
index 376e466..cb250dc 100644
--- a/glib/gmem.h
+++ b/glib/gmem.h
@@ -69,6 +69,10 @@ typedef struct _GMemVTable GMemVTable;
void g_free (gpointer mem);
+GLIB_AVAILABLE_IN_2_34
+void g_clear_pointer (gpointer *pp,
+ GDestroyNotify destroy);
+
gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
gpointer g_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
gpointer g_realloc (gpointer mem,
@@ -93,6 +97,20 @@ gpointer g_try_realloc_n (gpointer mem,
gsize n_blocks,
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
+#define g_clear_pointer(pp, destroy) \
+ G_STMT_START { \
+ G_STATIC_ASSERT (sizeof (*(pp)) == sizeof (gpointer)); \
+ /* Only one access, please */ \
+ gpointer *_pp = (gpointer *) pp; \
+ gpointer _p; \
+ \
+ do \
+ _p = g_atomic_pointer_get (_pp); \
+ while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (_pp, _p, NULL)); \
+ \
+ if (_p) \
+ ((GDestroyNotify) (destroy)) (_p); \
+ } G_STMT_END
/* Optimise: avoid the call to the (slower) _n function if we can
* determine at compile-time that no overflow happens.
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 69f14a8..a18cb75 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -3057,18 +3057,7 @@ g_object_unref (gpointer _object)
void
g_clear_object (volatile GObject **object_ptr)
{
- gpointer *ptr = (gpointer) object_ptr;
- gpointer old;
-
- /* This is a little frustrating.
- * Would be nice to have an atomic exchange (with no compare).
- */
- do
- old = g_atomic_pointer_get (ptr);
- while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (ptr, old, NULL));
-
- if (old)
- g_object_unref (old);
+ g_clear_pointer (object_ptr, g_object_unref);
}
/**
diff --git a/gobject/gobject.h b/gobject/gobject.h
index 3572736..d04ce2e 100644
--- a/gobject/gobject.h
+++ b/gobject/gobject.h
@@ -561,19 +561,7 @@ G_STMT_START { \
G_OBJECT_WARN_INVALID_PSPEC ((object), "property", (property_id), (pspec))
void g_clear_object (volatile GObject **object_ptr);
-#define g_clear_object(object_ptr) \
- G_STMT_START { \
- /* Only one access, please */ \
- gpointer *_p = (gpointer) (object_ptr); \
- gpointer _o; \
- \
- do \
- _o = g_atomic_pointer_get (_p); \
- while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (_p, _o, NULL));\
- \
- if (_o) \
- g_object_unref (_o); \
- } G_STMT_END
+#define g_clear_object(object_ptr) g_clear_pointer ((object_ptr), g_object_unref)
typedef struct {
/*<private>*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]