[glib] macro wrappers for g_once_init_enter/leave
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] macro wrappers for g_once_init_enter/leave
- Date: Tue, 4 Oct 2011 15:00:49 +0000 (UTC)
commit 794c1a30bc27b4c8d77537813acb1213d5ac80f2
Author: Ryan Lortie <desrt desrt ca>
Date: Mon Oct 3 14:40:00 2011 -0400
macro wrappers for g_once_init_enter/leave
Give the macro wrapper treatment to g_once_init_enter() and leave() in
the same style that we did for gatomic.
It is now possible to use these macros with any pointer-sized object,
and not just gsize. The leave() macro ensures that the initialisation
result is a compatible type with the pointer that it is being written
to.
Just like with gatomic, there could be problems caused by use of (void*)
casts. We'll see how that goes, and reevaluate if necessary.
https://bugzilla.gnome.org/show_bug.cgi?id=660743
glib/deprecated/gthread-deprecated.c | 7 ++++++
glib/deprecated/gthread.h | 2 +
glib/gthread.c | 15 +++++++-----
glib/gthread.h | 40 +++++++++++++++++++++------------
glib/tests/once.c | 12 ++++++++++
5 files changed, 55 insertions(+), 21 deletions(-)
---
diff --git a/glib/deprecated/gthread-deprecated.c b/glib/deprecated/gthread-deprecated.c
index 3b19970..5e45f7c 100644
--- a/glib/deprecated/gthread-deprecated.c
+++ b/glib/deprecated/gthread-deprecated.c
@@ -275,6 +275,13 @@ g_enumerable_thread_remove (GRealThread *thread)
G_UNLOCK (g_thread);
}
+/* GOnce {{{1 ------------------------------------------------------------- */
+gboolean
+g_once_init_enter_impl (volatile gsize *location)
+{
+ return (g_once_init_enter) (location);
+}
+
/* GStaticMutex {{{1 ------------------------------------------------------ */
/**
diff --git a/glib/deprecated/gthread.h b/glib/deprecated/gthread.h
index 00e92df..b6b9144 100644
--- a/glib/deprecated/gthread.h
+++ b/glib/deprecated/gthread.h
@@ -198,6 +198,8 @@ void g_static_private_set (GStaticPrivate *private_key,
GDestroyNotify notify);
void g_static_private_free (GStaticPrivate *private_key);
+gboolean g_once_init_enter_impl (volatile gsize *location);
+
G_END_DECLS
#endif /* __G_DEPRECATED_THREAD_H__ */
diff --git a/glib/gthread.c b/glib/gthread.c
index 75ccb3e..ab90d4e 100644
--- a/glib/gthread.c
+++ b/glib/gthread.c
@@ -753,8 +753,9 @@ g_once_impl (GOnce *once,
* Since: 2.14
*/
gboolean
-g_once_init_enter_impl (volatile gsize *value_location)
+(g_once_init_enter) (volatile void *pointer)
{
+ volatile gsize *value_location = pointer;
gboolean need_init = FALSE;
g_mutex_lock (&g_once_mutex);
if (g_atomic_pointer_get (value_location) == NULL)
@@ -777,7 +778,7 @@ g_once_init_enter_impl (volatile gsize *value_location)
* g_once_init_leave:
* @value_location: location of a static initializable variable
* containing 0
- * @initialization_value: new non-0 value for * value_location
+ * @result: new non-0 value for * value_location
*
* Counterpart to g_once_init_enter(). Expects a location of a static
* 0-initialized initialization variable, and an initialization value
@@ -788,14 +789,16 @@ g_once_init_enter_impl (volatile gsize *value_location)
* Since: 2.14
*/
void
-g_once_init_leave (volatile gsize *value_location,
- gsize initialization_value)
+(g_once_init_leave) (volatile void *pointer,
+ gsize result)
{
+ volatile gsize *value_location = pointer;
+
g_return_if_fail (g_atomic_pointer_get (value_location) == NULL);
- g_return_if_fail (initialization_value != 0);
+ g_return_if_fail (result != 0);
g_return_if_fail (g_once_init_list != NULL);
- g_atomic_pointer_set (value_location, initialization_value);
+ g_atomic_pointer_set (value_location, result);
g_mutex_lock (&g_once_mutex);
g_once_init_list = g_slist_remove (g_once_init_list, (void*) value_location);
g_cond_broadcast (&g_once_cond);
diff --git a/glib/gthread.h b/glib/gthread.h
index 8844cdb..3e3fd10 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -154,21 +154,31 @@ gpointer g_once_impl (GOnce *once, GThreadFunc func, gpointer arg);
g_once_impl ((once), (func), (arg)))
#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
-/* initialize-once guards, keyed by value_location */
-G_INLINE_FUNC gboolean g_once_init_enter (volatile gsize *value_location);
-gboolean g_once_init_enter_impl (volatile gsize *value_location);
-void g_once_init_leave (volatile gsize *value_location,
- gsize initialization_value);
-#if defined (G_CAN_INLINE) || defined (__G_THREAD_C__)
-G_INLINE_FUNC gboolean
-g_once_init_enter (volatile gsize *value_location)
-{
- if G_LIKELY ((gpointer) g_atomic_pointer_get (value_location) != NULL)
- return FALSE;
- else
- return g_once_init_enter_impl (value_location);
-}
-#endif /* G_CAN_INLINE || __G_THREAD_C__ */
+/* initialize-once guards, keyed by location */
+gboolean g_once_init_enter (volatile void *location);
+void g_once_init_leave (volatile void *location,
+ gsize result);
+
+#ifdef __GNUC__
+# define g_once_init_enter(location) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(location) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(location) : 0); \
+ (!g_atomic_pointer_get (location) && \
+ g_once_init_enter (location)); \
+ }))
+# define g_once_init_leave(location, result) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(location) == sizeof (gpointer)); \
+ (void) (0 ? *(location) = (result) : 0); \
+ g_once_init_leave ((location), (gsize) (result)); \
+ }))
+#else
+# define g_once_init_enter(location) \
+ (g_once_init_enter((location)))
+# define g_once_init_leave(location, result) \
+ (g_once_init_leave((location), (gsize) (result)))
+#endif
#define G_LOCK_NAME(name) g__ ## name ## _lock
#define G_LOCK_DEFINE_STATIC(name) static G_LOCK_DEFINE (name)
diff --git a/glib/tests/once.c b/glib/tests/once.c
index 588754c..dcb8e29 100644
--- a/glib/tests/once.c
+++ b/glib/tests/once.c
@@ -112,6 +112,17 @@ test_once3 (void)
g_assert_cmpint (shared, ==, 42);
}
+static void
+test_once4 (void)
+{
+ static const gchar *val;
+
+ if (g_once_init_enter (&val))
+ g_once_init_leave (&val, "foo");
+
+ g_assert_cmpstr (val, ==, "foo");
+}
+
int
main (int argc, char *argv[])
{
@@ -120,6 +131,7 @@ main (int argc, char *argv[])
g_test_add_func ("/thread/once1", test_once1);
g_test_add_func ("/thread/once2", test_once2);
g_test_add_func ("/thread/once3", test_once3);
+ g_test_add_func ("/thread/once4", test_once4);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]