[glib/wip/mutexes] Add a new recursive mutex type, GRecMutex



commit f787d77210b3f84467dbdb93f2c74b9c98452d20
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Sep 21 14:36:53 2011 -0400

    Add a new recursive mutex type, GRecMutex
    
    This is implemented using the native facilities of each platform instead
    of manually.

 glib/glib.symbols    |    5 +++
 glib/gthread-posix.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/gthread-win32.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++
 glib/gthread.h       |   13 +++++++++
 4 files changed, 158 insertions(+), 0 deletions(-)
---
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 7f79813..03cbb44 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1624,3 +1624,8 @@ g_rw_lock_reader_unlock
 g_rw_lock_writer_lock
 g_rw_lock_writer_trylock
 g_rw_lock_writer_unlock
+g_rec_mutex_clear
+g_rec_mutex_init
+g_rec_mutex_lock
+g_rec_mutex_trylock
+g_rec_mutex_unlock
diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c
index c4fd6f2..fa13dda 100644
--- a/glib/gthread-posix.c
+++ b/glib/gthread-posix.c
@@ -43,6 +43,7 @@
 
 #include "gthread.h"
 #include "gthreadprivate.h"
+#include "gslice.h"
 
 #include <pthread.h>
 #include <stdlib.h>
@@ -197,6 +198,77 @@ g_mutex_trylock (GMutex *mutex)
   return FALSE;
 }
 
+/* {{{1 GRecMutex */
+
+static pthread_mutex_t *
+g_rec_mutex_impl_new (void)
+{
+  pthread_mutexattr_t attr;
+  pthread_mutex_t *mutex;
+
+  mutex = g_slice_new (pthread_mutex_t);
+  pthread_mutexattr_init (&attr);
+  pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init (mutex, &attr);
+  pthread_mutexattr_destroy (&attr);
+
+  return mutex;
+}
+
+static void
+g_rec_mutex_impl_free (pthread_mutex_t *mutex)
+{
+  pthread_mutex_destroy (mutex);
+  g_slice_free (pthread_mutex_t, mutex);
+}
+
+static pthread_mutex_t *
+g_rec_mutex_get_impl (GRecMutex *mutex)
+{
+  pthread_mutex_t *impl = mutex->impl;
+
+  if G_UNLIKELY (mutex->impl == NULL)
+    {
+      impl = g_rec_mutex_impl_new ();
+      if (!g_atomic_pointer_compare_and_exchange (&mutex->impl, NULL, impl))
+        g_rec_mutex_impl_free (impl);
+      impl = mutex->impl;
+    }
+
+  return impl;
+}
+
+void
+g_rec_mutex_init (GRecMutex *mutex)
+{
+  mutex->impl = g_rec_mutex_impl_new ();
+}
+
+void
+g_rec_mutex_clear (GRecMutex *mutex)
+{
+  if (mutex->impl)
+    g_rec_mutex_impl_free (mutex->impl);
+}
+
+void
+g_rec_mutex_lock (GRecMutex *mutex)
+{
+  pthread_mutex_lock (g_rec_mutex_get_impl (mutex));
+}
+
+void
+g_rec_mutex_unlock (GRecMutex *mutex)
+{
+  pthread_mutex_unlock (mutex->impl);
+}
+
+gboolean
+g_rec_mutex_trylock (GRecMutex *mutex)
+{
+  return pthread_mutex_trylock (g_rec_mutex_get_impl (mutex));
+}
+
 /* {{{1 GRWLock */
 
 void
diff --git a/glib/gthread-win32.c b/glib/gthread-win32.c
index 1213143..f1533c7 100644
--- a/glib/gthread-win32.c
+++ b/glib/gthread-win32.c
@@ -44,6 +44,7 @@
 
 #include "gthread.h"
 #include "gthreadprivate.h"
+#include "gslice.h"
 
 #include <windows.h>
 
@@ -154,6 +155,73 @@ g_mutex_unlock (GMutex *mutex)
   g_thread_impl_vtable.ReleaseSRWLockExclusive (mutex);
 }
 
+/* {{{1 GRecMutex */
+
+static CRITICAL_SECTION *
+g_rec_mutex_impl_new (void)
+{
+  CRITICAL_SECTION *cs;
+
+  cs = g_slice_new (CRITICAL_SECTION);
+  InitializeCriticalSection (cs);
+
+  return cs;
+}
+
+static void
+g_rec_mutex_impl_free (CRITICAL_SECTION *cs)
+{
+  DeleteCriticalSection (cs);
+  g_slice_free (CRITICAL_SECTION, cs);
+}
+
+static CRITICAL_SECTION *
+g_rec_mutex_get_impl (GRecMutex *mutex)
+{
+  CRITICAL_SECTION *impl = mutex->impl;
+
+  if G_UNLIKELY (mutex->impl == NULL)
+    {
+      impl = g_rec_mutex_impl_new ();
+      if (InterlockedCompareExchangePointer (&mutex->impl, impl, NULL) != NULL)
+        g_rec_mutex_impl_free (impl);
+      impl = mutex->impl;
+    }
+
+  return impl;
+}
+
+void
+g_rec_mutex_init (GRecMutex *mutex)
+{
+  mutex->impl = g_rec_mutex_impl_new ();
+}
+
+void
+g_rec_mutex_clear (GRecMutex *mutex)
+{
+  if (mutex->impl)
+    g_rec_mutex_impl_free (mutex->impl);
+}
+
+void
+g_rec_mutex_lock (GRecMutex *mutex)
+{
+  EnterCriticalSection (g_rec_mutex_get_impl (mutex));
+}
+
+void
+g_rec_mutex_unlock (GRecMutex *mutex)
+{
+  LeaveCriticalSection (mutex->impl);
+}
+
+gboolean
+g_rec_mutex_trylock (GRecMutex *mutex)
+{
+  return TryEnterCriticalSection (g_rec_mutex_get_impl (mutex));
+}
+
 /* {{{1 GRWLock */
 
 void
diff --git a/glib/gthread.h b/glib/gthread.h
index 161de59..48d5326 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -53,6 +53,7 @@ typedef gpointer (*GThreadFunc) (gpointer data);
 typedef struct _GThread         GThread;
 
 typedef struct _GMutex          GMutex;
+typedef struct _GRecMutex       GRecMutex;
 typedef struct _GRWLock         GRWLock;
 typedef struct _GCond           GCond;
 typedef struct _GPrivate        GPrivate;
@@ -101,6 +102,12 @@ struct _GCond
 
 #endif
 
+#define G_REC_MUTEX_INIT { NULL }
+struct _GRecMutex
+{
+  gpointer impl;
+};
+
 /* initializes the mutex/cond/private implementation for glib, might
  * only be called once, and must not be called directly or indirectly
  * from another glib-function, e.g. as a callback.
@@ -314,6 +321,12 @@ void                    g_rw_lock_reader_lock                           (GRWLock
 gboolean                g_rw_lock_reader_trylock                        (GRWLock        *lock);
 void                    g_rw_lock_reader_unlock                         (GRWLock        *lock);
 
+void                    g_rec_mutex_init                                (GRecMutex      *rec_mutex);
+void                    g_rec_mutex_clear                               (GRecMutex      *rec_mutex);
+void                    g_rec_mutex_lock                                (GRecMutex      *rec_mutex);
+gboolean                g_rec_mutex_trylock                             (GRecMutex      *rec_mutex);
+void                    g_rec_mutex_unlock                              (GRecMutex      *rec_mutex);
+
 GCond *                 g_cond_new                                      (void);
 void                    g_cond_free                                     (GCond          *cond);
 void                    g_cond_init                                     (GCond          *cond);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]