From 794c1a30bc27b4c8d77537813acb1213d5ac80f2 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Mon, 3 Oct 2011 14:40:00 -0400 Subject: [PATCH] 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 (); } -- 2.7.4