summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2010-10-08 16:53:22 +0200
committerEdward Hervey <bilboed@bilboed.com>2010-10-08 17:22:52 +0200
commite7f6d8dff011efb5e69b5db01e3ae3d8fecd6bf9 (patch)
tree2ccdddf3c2fe9add91652bcd1f4be621a514ab7a
parentd9aeee538e989010050c0a32626d4f5ccaf577fd (diff)
Initial native RWLock implementation
-rw-r--r--configure.ac49
-rw-r--r--glib/glib.symbols3
-rw-r--r--glib/gthread.c102
-rw-r--r--glib/gthread.h47
4 files changed, 169 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac
index 5668592ab..7ec67412d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2028,6 +2028,7 @@ dnl determination of G_THREAD_LIBS
dnl ******************************
mutex_has_default=no
+rwlock_has_default=no
case $have_threads in
posix|dce)
glib_save_CPPFLAGS="$CPPFLAGS"
@@ -2112,6 +2113,10 @@ case $have_threads in
mutex_default_type='pthread_mutex_t'
mutex_default_init='PTHREAD_MUTEX_INITIALIZER'
mutex_header_file='pthread.h'
+ rwlock_has_default=yes
+ rwlock_default_type='pthread_rwlock_t'
+ rwlock_default_init='PTHREAD_RWLOCK_INITIALIZER'
+ rwlock_header_file='pthread.h'
if test "x$have_threads" = "xposix"; then
g_threads_impl="POSIX"
else
@@ -2375,6 +2380,17 @@ if test $mutex_has_default = yes ; then
if test x"$glib_cv_byte_contents_gmutex" = xno; then
mutex_has_default=no
fi
+ GLIB_SIZEOF([#include <$rwlock_header_file>],
+ $rwlock_default_type,
+ grwlock)
+ GLIB_BYTE_CONTENTS([#include <$rwlock_header_file>],
+ $rwlock_default_type,
+ grwlock,
+ $glib_cv_sizeof_grwlock,
+ $rwlock_default_init)
+ if test x"$glib_cv_byte_contents_grwlock" = xno; then
+ rwlock_has_default=no
+ fi
CPPFLAGS="$glib_save_CPPFLAGS"
LIBS="$glib_save_LIBS"
fi
@@ -3191,6 +3207,36 @@ typedef struct _GMutex* GStaticMutex;
_______EOF
fi
+ if test x$g_rw_lock_has_default = xyes; then
+ cat >>$outfile <<_______EOF
+
+typedef struct _GStaticRWLock GStaticRWLock;
+struct _GStaticRWLock
+{
+ struct _GRWLock *runtime_rwlock;
+ union {
+ char pad[[$g_rw_lock_sizeof]];
+ double dummy_double;
+ void *dummy_pointer;
+ long dummy_long;
+ } static_rwlock;
+};
+#define G_STATIC_RW_LOCK_INIT { NULL, { { $g_rw_lock_contents} } }
+#define g_static_rw_lock_get_rw_lock(rwlock) \\
+ (g_thread_use_default_impl ? ((GRWLock*)(gpointer) ((rwlock)->static_rwlock.pad)) : \\
+ g_static_rw_lock_get_rw_lock_impl_shortcut (&((rwlock)->runtime_rwlock)))
+
+_______EOF
+ else
+ cat >>$outfile <<_______EOF
+typedef struct _GRWLock* GStaticRWLock;
+#define G_STATIC_RW_LOCK_INIT NULL
+#define g_static_rw_lock_get_rw_lock(rwlock) \\
+ (g_static_rw_lock_get_rw_lock_impl_shortcut (rwlock))
+_______EOF
+ fi
+
+
cat >>$outfile <<_______EOF
/* This represents a system thread as used by the implementation. An
* alien implementaion, as loaded by g_thread_init can only count on
@@ -3584,6 +3630,9 @@ g_mutex_has_default="$mutex_has_default"
g_mutex_sizeof="$glib_cv_sizeof_gmutex"
g_system_thread_sizeof="$glib_cv_sizeof_system_thread"
g_mutex_contents="$glib_cv_byte_contents_gmutex"
+g_rw_lock_has_default="$rwlock_has_default"
+g_rw_lock_sizeof="$glib_cv_sizeof_grwlock"
+g_rw_lock_contents="$glib_cv_byte_contents_grwlock"
g_memory_barrier_needed="$glib_memory_barrier_needed"
diff --git a/glib/glib.symbols b/glib/glib.symbols
index c9984e8e7..0b74495af 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1388,7 +1388,10 @@ g_static_rec_mutex_trylock
g_static_rec_mutex_unlock
g_static_rec_mutex_unlock_full
g_static_rw_lock_free
+g_static_rw_lock_free_new
+g_static_rw_lock_get_rw_lock_impl
g_static_rw_lock_init
+g_static_rw_lock_init_new
g_static_rw_lock_reader_lock
g_static_rw_lock_reader_trylock
g_static_rw_lock_reader_unlock
diff --git a/glib/gthread.c b/glib/gthread.c
index d83ed95c3..10675e51b 100644
--- a/glib/gthread.c
+++ b/glib/gthread.c
@@ -2269,8 +2269,11 @@ g_thread_self (void)
* can be used. Alternatively you can initialize it with
* #G_STATIC_RW_LOCK_INIT.
**/
+
+/* New implementation (native) */
+
void
-g_static_rw_lock_init (GStaticRWLock* lock)
+g_static_rw_lock_init_new (GStaticRWLock* lock)
{
static const GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
@@ -2279,6 +2282,87 @@ g_static_rw_lock_init (GStaticRWLock* lock)
*lock = init_lock;
}
+GRWLock*
+g_static_rw_lock_get_rw_lock_impl (GRWLock **rwlock)
+{
+ GRWLock *result;
+
+ if (!g_thread_supported ())
+ return NULL;
+
+ result = g_atomic_pointer_get (rwlock);
+
+ if (G_UNLIKELY (!result))
+ {
+ g_assert (g_once_mutex);
+
+ g_mutex_lock (g_once_mutex);
+
+ result = *rwlock;
+ if (G_UNLIKELY (!result))
+ {
+ result = g_rw_lock_new ();
+ g_atomic_pointer_set (rwlock, result);
+ }
+
+ g_mutex_unlock (g_once_mutex);
+ }
+
+ return result;
+
+}
+
+void
+g_static_rw_lock_free_new (GStaticRWLock* lock)
+{
+ GRWLock **runtime_rwlock;
+
+ g_return_if_fail (lock);
+
+ runtime_rwlock = ((GRWLock**) lock);
+ if (*runtime_rwlock)
+ g_rw_lock_free (*runtime_rwlock);
+
+ *runtime_rwlock = NULL;
+}
+
+/* Old implementation,
+ * we need to keep the symbols around for ABI compatibility */
+
+#undef g_static_rw_lock_init
+#undef g_static_rw_lock_free
+#undef g_static_rw_lock_reader_lock
+#undef g_static_rw_lock_reader_trylock
+#undef g_static_rw_lock_reader_unlock
+#undef g_static_rw_lock_writer_lock
+#undef g_static_rw_lock_writer_trylock
+#undef g_static_rw_lock_writer_unlock
+
+
+#define G_STATIC_RW_LOCK_OLD_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 }
+typedef struct _GStaticRWLockOLD GStaticRWLockOLD;
+struct _GStaticRWLockOLD
+{
+ GStaticMutex mutex;
+ GCond *read_cond;
+ GCond *write_cond;
+ guint read_counter;
+ gboolean have_writer;
+ guint want_to_read;
+ guint want_to_write;
+};
+
+
+void
+g_static_rw_lock_init (GStaticRWLockOLD* lock)
+{
+ static const GStaticRWLockOLD init_lock = G_STATIC_RW_LOCK_OLD_INIT;
+
+ g_return_if_fail (lock);
+
+ *lock = init_lock;
+}
+
inline static void
g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
{
@@ -2288,7 +2372,7 @@ g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
}
inline static void
-g_static_rw_lock_signal (GStaticRWLock* lock)
+g_static_rw_lock_signal (GStaticRWLockOLD* lock)
{
if (lock->want_to_write && lock->write_cond)
g_cond_signal (lock->write_cond);
@@ -2313,7 +2397,7 @@ g_static_rw_lock_signal (GStaticRWLock* lock)
* to writer preference.
**/
void
-g_static_rw_lock_reader_lock (GStaticRWLock* lock)
+g_static_rw_lock_reader_lock (GStaticRWLockOLD* lock)
{
g_return_if_fail (lock);
@@ -2341,7 +2425,7 @@ g_static_rw_lock_reader_lock (GStaticRWLock* lock)
* g_static_rw_lock_reader_unlock().
**/
gboolean
-g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
+g_static_rw_lock_reader_trylock (GStaticRWLockOLD* lock)
{
gboolean ret_val = FALSE;
@@ -2369,7 +2453,7 @@ g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
* and can lock @lock for writing.
**/
void
-g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
+g_static_rw_lock_reader_unlock (GStaticRWLockOLD* lock)
{
g_return_if_fail (lock);
@@ -2396,7 +2480,7 @@ g_static_rw_lock_reader_unlock (GStaticRWLock* lock)
* unlocked by g_static_rw_lock_writer_unlock().
**/
void
-g_static_rw_lock_writer_lock (GStaticRWLock* lock)
+g_static_rw_lock_writer_lock (GStaticRWLockOLD* lock)
{
g_return_if_fail (lock);
@@ -2423,7 +2507,7 @@ g_static_rw_lock_writer_lock (GStaticRWLock* lock)
* lock has to be unlocked by g_static_rw_lock_writer_unlock().
**/
gboolean
-g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
+g_static_rw_lock_writer_trylock (GStaticRWLockOLD* lock)
{
gboolean ret_val = FALSE;
@@ -2454,7 +2538,7 @@ g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
* lock @lock for reading.
**/
void
-g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
+g_static_rw_lock_writer_unlock (GStaticRWLockOLD* lock)
{
g_return_if_fail (lock);
@@ -2479,7 +2563,7 @@ g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
* freed, you should also free the #GStaticRWLock.
**/
void
-g_static_rw_lock_free (GStaticRWLock* lock)
+g_static_rw_lock_free (GStaticRWLockOLD* lock)
{
g_return_if_fail (lock);
diff --git a/glib/gthread.h b/glib/gthread.h
index 3fd71dba4..60ff912af 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -167,6 +167,13 @@ GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex);
(g_atomic_pointer_get (mutex) ? *(mutex) : \
g_static_mutex_get_mutex_impl (mutex))
+/* internal function for fallback static rwlock implementation */
+GRWLock* g_static_rw_lock_get_rw_lock_impl (GRWLock **a);
+
+#define g_static_rw_lock_get_rw_lock_impl_shortcut(rw_lock) \
+ (g_atomic_pointer_get (rw_lock) ? *(rw_lock) : \
+ g_static_rw_lock_get_rw_lock_impl (rw_lock))
+
/* shorthands for conditional and unconditional function calls */
#define G_THREAD_UF(op, arglist) \
@@ -339,29 +346,23 @@ void g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
guint g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex);
void g_static_rec_mutex_free (GStaticRecMutex *mutex);
-typedef struct _GStaticRWLock GStaticRWLock;
-struct _GStaticRWLock
-{
- /*< private >*/
- GStaticMutex mutex;
- GCond *read_cond;
- GCond *write_cond;
- guint read_counter;
- gboolean have_writer;
- guint want_to_read;
- guint want_to_write;
-};
-
-#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 }
-
-void g_static_rw_lock_init (GStaticRWLock* lock);
-void g_static_rw_lock_reader_lock (GStaticRWLock* lock);
-gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock);
-void g_static_rw_lock_reader_unlock (GStaticRWLock* lock);
-void g_static_rw_lock_writer_lock (GStaticRWLock* lock);
-gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock);
-void g_static_rw_lock_writer_unlock (GStaticRWLock* lock);
-void g_static_rw_lock_free (GStaticRWLock* lock);
+#define g_static_rw_lock_reader_lock(b) \
+ g_rw_lock_reader_lock (g_static_rw_lock_get_rw_lock (b))
+#define g_static_rw_lock_reader_trylock(c) \
+ g_rw_lock_reader_trylock (g_static_rw_lock_get_rw_lock (c))
+#define g_static_rw_lock_reader_unlock(d) \
+ g_rw_lock_reader_unlock (g_static_rw_lock_get_rw_lock (d))
+#define g_static_rw_lock_writer_lock(e) \
+ g_rw_lock_writer_lock (g_static_rw_lock_get_rw_lock (e))
+#define g_static_rw_lock_writer_trylock(f) \
+ g_rw_lock_writer_trylock (g_static_rw_lock_get_rw_lock (f))
+#define g_static_rw_lock_writer_unlock(g) \
+ g_rw_lock_writer_unlock (g_static_rw_lock_get_rw_lock (g))
+
+#define g_static_rw_lock_init g_static_rw_lock_init_new
+#define g_static_rw_lock_free g_static_rw_lock_free_new
+void g_static_rw_lock_init_new (GStaticRWLock* lock);
+void g_static_rw_lock_free_new (GStaticRWLock* lock);
void g_thread_foreach (GFunc thread_func,
gpointer user_data);