diff options
author | Edward Hervey <bilboed@bilboed.com> | 2010-10-08 16:53:22 +0200 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2010-10-08 17:22:52 +0200 |
commit | e7f6d8dff011efb5e69b5db01e3ae3d8fecd6bf9 (patch) | |
tree | 2ccdddf3c2fe9add91652bcd1f4be621a514ab7a | |
parent | d9aeee538e989010050c0a32626d4f5ccaf577fd (diff) |
Initial native RWLock implementation
-rw-r--r-- | configure.ac | 49 | ||||
-rw-r--r-- | glib/glib.symbols | 3 | ||||
-rw-r--r-- | glib/gthread.c | 102 | ||||
-rw-r--r-- | glib/gthread.h | 47 |
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); |