implemented g_once_init_enter(), g_once_init_enter_impl() and
authorTim Janik <timj@imendio.com>
Tue, 10 Jul 2007 10:30:36 +0000 (10:30 +0000)
committerTim Janik <timj@src.gnome.org>
Tue, 10 Jul 2007 10:30:36 +0000 (10:30 +0000)
Tue Jul 10 12:24:35 2007  Tim Janik  <timj@imendio.com>

        * glib/gthread.[hc]: implemented g_once_init_enter(),
        g_once_init_enter_impl() and g_once_init_leave(), based on a patch by
        Antoine Tremblay, fixes #65041.
        adapted exported inline function mechanism from gutils.[hc] for inlining
        g_once_init_enter_impl() in gthread.[hc].

svn path=/trunk/; revision=5616

ChangeLog
glib/glib.symbols
glib/gthread.c
glib/gthread.h

index cb1a1ed..18f68fc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Tue Jul 10 12:24:35 2007  Tim Janik  <timj@imendio.com>
+
+       * glib/gthread.[hc]: implemented g_once_init_enter(),
+       g_once_init_enter_impl() and g_once_init_leave(), based on a patch by
+       Antoine Tremblay, fixes #65041.
+       adapted exported inline function mechanism from gutils.[hc] for inlining
+       g_once_init_enter_impl() in gthread.[hc].
+
 2007-07-09  Matthias Clasen  <mclasen@redhat.com>
 
        * NEWS: Updates
index 5434e24..5ab5853 100644 (file)
@@ -1172,7 +1172,10 @@ g_str_hash
 #if IN_HEADER(__G_THREAD_H__)
 #if IN_FILE(__G_THREAD_C__)
 g_once_impl
+g_once_init_enter_impl
+g_once_init_leave
 #ifdef INCLUDE_INTERNAL_SYMBOLS
+g_once_init_enter
 g_thread_init_glib
 #endif
 #ifdef INCLUDE_VARIABLES
index c47a1b3..e040524 100644 (file)
  * MT safe
  */
 
+/* implement gthread.h's inline functions */
+#define G_IMPLEMENT_INLINES 1
+#define __G_THREAD_C__
+
 #include "config.h"
 
 #include "glib.h"
@@ -121,6 +125,7 @@ static GCond    *g_once_cond = NULL;
 static GPrivate *g_thread_specific_private = NULL;
 static GRealThread *g_thread_all_threads = NULL;
 static GSList   *g_thread_free_indeces = NULL;
+static GSList*   g_once_init_list = NULL;
 
 G_LOCK_DEFINE_STATIC (g_thread);
 
@@ -194,6 +199,41 @@ g_once_impl (GOnce       *once,
   return once->retval;
 }
 
+gboolean
+g_once_init_enter_impl (volatile gsize *value_location)
+{
+  gboolean need_init;
+  g_mutex_lock (g_once_mutex);
+  if (!g_once_init_list || !g_slist_find (g_once_init_list, (void*) value_location))
+    {
+      g_once_init_list = g_slist_prepend (g_once_init_list, (void*) value_location);
+      need_init = TRUE;
+    }
+  else
+    {
+      while (g_slist_find (g_once_init_list, (void*) value_location))
+        g_cond_wait (g_once_cond, g_once_mutex);
+      need_init = FALSE;
+    }
+  g_mutex_unlock (g_once_mutex);
+  return need_init;
+}
+
+void
+g_once_init_leave (volatile gsize *value_location,
+                   gsize           initialization_value)
+{
+  g_return_if_fail (g_atomic_pointer_get (value_location) == 0);
+  g_return_if_fail (initialization_value != 0);
+  g_return_if_fail (g_once_init_list != NULL);
+
+  g_atomic_pointer_set (value_location, initialization_value);
+  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);
+  g_mutex_unlock (g_once_mutex);
+}
+
 void
 g_static_mutex_init (GStaticMutex *mutex)
 {
index 79099f1..2076185 100644 (file)
@@ -29,7 +29,8 @@
 
 #include <glib/gerror.h>
 #include <glib/gtypes.h>
-#include <glib/gatomic.h>  /* for g_atomic_pointer_get */
+#include <glib/gutils.h>        /* for G_INLINE_FUNC */
+#include <glib/gatomic.h>       /* for g_atomic_pointer_get */
 
 G_BEGIN_DECLS
 
@@ -321,7 +322,23 @@ gpointer g_once_impl (GOnce *once, GThreadFunc func, gpointer arg);
    (once)->retval : \
    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 (g_atomic_pointer_get (value_location) !=0)
+    return FALSE;
+  else
+    return g_once_init_enter_impl (value_location);
+}
+#endif /* G_CAN_INLINE || __G_THREAD_C__ */
+
 /* these are some convenience macros that expand to nothing if GLib
  * was configured with --disable-threads. for using StaticMutexes,
  * you define them with G_LOCK_DEFINE_STATIC (name) or G_LOCK_DEFINE (name)