mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-21 16:38:54 +02:00
Add a new recursive mutex type, GRecMutex
This is implemented using the native facilities of each platform instead of manually.
This commit is contained in:
@@ -1624,3 +1624,8 @@ g_rw_lock_reader_unlock
|
|||||||
g_rw_lock_writer_lock
|
g_rw_lock_writer_lock
|
||||||
g_rw_lock_writer_trylock
|
g_rw_lock_writer_trylock
|
||||||
g_rw_lock_writer_unlock
|
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
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include "gthread.h"
|
#include "gthread.h"
|
||||||
#include "gthreadprivate.h"
|
#include "gthreadprivate.h"
|
||||||
|
#include "gslice.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -197,6 +198,77 @@ g_mutex_trylock (GMutex *mutex)
|
|||||||
return FALSE;
|
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 */
|
/* {{{1 GRWLock */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include "gthread.h"
|
#include "gthread.h"
|
||||||
#include "gthreadprivate.h"
|
#include "gthreadprivate.h"
|
||||||
|
#include "gslice.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
@@ -154,6 +155,73 @@ g_mutex_unlock (GMutex *mutex)
|
|||||||
g_thread_impl_vtable.ReleaseSRWLockExclusive (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 */
|
/* {{{1 GRWLock */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -53,6 +53,7 @@ typedef gpointer (*GThreadFunc) (gpointer data);
|
|||||||
typedef struct _GThread GThread;
|
typedef struct _GThread GThread;
|
||||||
|
|
||||||
typedef struct _GMutex GMutex;
|
typedef struct _GMutex GMutex;
|
||||||
|
typedef struct _GRecMutex GRecMutex;
|
||||||
typedef struct _GRWLock GRWLock;
|
typedef struct _GRWLock GRWLock;
|
||||||
typedef struct _GCond GCond;
|
typedef struct _GCond GCond;
|
||||||
typedef struct _GPrivate GPrivate;
|
typedef struct _GPrivate GPrivate;
|
||||||
@@ -101,6 +102,12 @@ struct _GCond
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define G_REC_MUTEX_INIT { NULL }
|
||||||
|
struct _GRecMutex
|
||||||
|
{
|
||||||
|
gpointer impl;
|
||||||
|
};
|
||||||
|
|
||||||
/* initializes the mutex/cond/private implementation for glib, might
|
/* initializes the mutex/cond/private implementation for glib, might
|
||||||
* only be called once, and must not be called directly or indirectly
|
* only be called once, and must not be called directly or indirectly
|
||||||
* from another glib-function, e.g. as a callback.
|
* 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);
|
gboolean g_rw_lock_reader_trylock (GRWLock *lock);
|
||||||
void g_rw_lock_reader_unlock (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);
|
GCond * g_cond_new (void);
|
||||||
void g_cond_free (GCond *cond);
|
void g_cond_free (GCond *cond);
|
||||||
void g_cond_init (GCond *cond);
|
void g_cond_init (GCond *cond);
|
||||||
|
Reference in New Issue
Block a user