[glib] macro wrappers for g_once_init_enter/leave



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]