+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
#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
* MT safe
*/
+/* implement gthread.h's inline functions */
+#define G_IMPLEMENT_INLINES 1
+#define __G_THREAD_C__
+
#include "config.h"
#include "glib.h"
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);
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)
{
#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
(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)