mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-14 05:16:18 +01:00
Merge branch 'wip/kalev/recursive-mutex-locker' into 'master'
Add GRecMutexLocker See merge request GNOME/glib!528
This commit is contained in:
commit
8aff74e213
@ -733,6 +733,11 @@ g_rec_mutex_lock
|
|||||||
g_rec_mutex_trylock
|
g_rec_mutex_trylock
|
||||||
g_rec_mutex_unlock
|
g_rec_mutex_unlock
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
GRecMutexLocker
|
||||||
|
g_rec_mutex_locker_new
|
||||||
|
g_rec_mutex_locker_free
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
GRWLock
|
GRWLock
|
||||||
g_rw_lock_init
|
g_rw_lock_init
|
||||||
|
@ -75,6 +75,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GStringChunk, g_string_chunk_free)
|
|||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GThread, g_thread_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GThread, g_thread_unref)
|
||||||
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GMutex, g_mutex_clear)
|
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GMutex, g_mutex_clear)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMutexLocker, g_mutex_locker_free)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMutexLocker, g_mutex_locker_free)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GRecMutexLocker, g_rec_mutex_locker_free)
|
||||||
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GCond, g_cond_clear)
|
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GCond, g_cond_clear)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTimer, g_timer_destroy)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTimer, g_timer_destroy)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTimeZone, g_time_zone_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTimeZone, g_time_zone_unref)
|
||||||
|
@ -336,6 +336,75 @@ g_mutex_locker_free (GMutexLocker *locker)
|
|||||||
g_mutex_unlock ((GMutex *) locker);
|
g_mutex_unlock ((GMutex *) locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GRecMutexLocker:
|
||||||
|
*
|
||||||
|
* Opaque type. See g_rec_mutex_locker_new() for details.
|
||||||
|
* Since: 2.60
|
||||||
|
*/
|
||||||
|
typedef void GRecMutexLocker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rec_mutex_locker_new:
|
||||||
|
* @rec_mutex: a recursive mutex to lock
|
||||||
|
*
|
||||||
|
* Lock @rec_mutex and return a new #GRecMutexLocker. Unlock with
|
||||||
|
* g_rec_mutex_locker_free(). Using g_rec_mutex_unlock() on @rec_mutex
|
||||||
|
* while a #GRecMutexLocker exists can lead to undefined behaviour.
|
||||||
|
*
|
||||||
|
* This is intended to be used with g_autoptr(). Note that g_autoptr()
|
||||||
|
* is only available when using GCC or clang, so the following example
|
||||||
|
* will only work with those compilers:
|
||||||
|
* |[
|
||||||
|
* typedef struct
|
||||||
|
* {
|
||||||
|
* ...
|
||||||
|
* GRecMutex rec_mutex;
|
||||||
|
* ...
|
||||||
|
* } MyObject;
|
||||||
|
*
|
||||||
|
* static void
|
||||||
|
* my_object_do_stuff (MyObject *self)
|
||||||
|
* {
|
||||||
|
* g_autoptr(GRecMutexLocker) locker = g_rec_mutex_locker_new (&self->rec_mutex);
|
||||||
|
*
|
||||||
|
* // Code with rec_mutex locked here
|
||||||
|
*
|
||||||
|
* if (cond)
|
||||||
|
* // No need to unlock
|
||||||
|
* return;
|
||||||
|
*
|
||||||
|
* // Optionally early unlock
|
||||||
|
* g_clear_pointer (&locker, g_rec_mutex_locker_free);
|
||||||
|
*
|
||||||
|
* // Code with rec_mutex unlocked here
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Returns: a #GRecMutexLocker
|
||||||
|
* Since: 2.60
|
||||||
|
*/
|
||||||
|
static inline GRecMutexLocker *
|
||||||
|
g_rec_mutex_locker_new (GRecMutex *rec_mutex)
|
||||||
|
{
|
||||||
|
g_rec_mutex_lock (rec_mutex);
|
||||||
|
return (GRecMutexLocker *) rec_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_rec_mutex_locker_free:
|
||||||
|
* @locker: a GRecMutexLocker
|
||||||
|
*
|
||||||
|
* Unlock @locker's recursive mutex. See g_rec_mutex_locker_new() for details.
|
||||||
|
*
|
||||||
|
* Since: 2.60
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
g_rec_mutex_locker_free (GRecMutexLocker *locker)
|
||||||
|
{
|
||||||
|
g_rec_mutex_unlock ((GRecMutex *) locker);
|
||||||
|
}
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_THREAD_H__ */
|
#endif /* __G_THREAD_H__ */
|
||||||
|
@ -329,10 +329,30 @@ test_g_mutex (void)
|
|||||||
g_mutex_init (&val);
|
g_mutex_init (&val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Thread function to check that a mutex given in @data is locked */
|
||||||
|
static gpointer
|
||||||
|
mutex_locked_thread (gpointer data)
|
||||||
|
{
|
||||||
|
GMutex *mutex = (GMutex *) data;
|
||||||
|
g_assert_false (g_mutex_trylock (mutex));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread function to check that a mutex given in @data is unlocked */
|
||||||
|
static gpointer
|
||||||
|
mutex_unlocked_thread (gpointer data)
|
||||||
|
{
|
||||||
|
GMutex *mutex = (GMutex *) data;
|
||||||
|
g_assert_true (g_mutex_trylock (mutex));
|
||||||
|
g_mutex_unlock (mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_g_mutex_locker (void)
|
test_g_mutex_locker (void)
|
||||||
{
|
{
|
||||||
GMutex mutex;
|
GMutex mutex;
|
||||||
|
GThread *thread;
|
||||||
|
|
||||||
g_mutex_init (&mutex);
|
g_mutex_init (&mutex);
|
||||||
|
|
||||||
@ -340,8 +360,58 @@ test_g_mutex_locker (void)
|
|||||||
{
|
{
|
||||||
g_autoptr(GMutexLocker) val = g_mutex_locker_new (&mutex);
|
g_autoptr(GMutexLocker) val = g_mutex_locker_new (&mutex);
|
||||||
|
|
||||||
g_assert (val != NULL);
|
g_assert_nonnull (val);
|
||||||
|
|
||||||
|
/* Verify that the mutex is actually locked */
|
||||||
|
thread = g_thread_new ("mutex locked", mutex_locked_thread, &mutex);
|
||||||
|
g_thread_join (thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify that the mutex is unlocked again */
|
||||||
|
thread = g_thread_new ("mutex unlocked", mutex_unlocked_thread, &mutex);
|
||||||
|
g_thread_join (thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread function to check that a recursive mutex given in @data is locked */
|
||||||
|
static gpointer
|
||||||
|
rec_mutex_locked_thread (gpointer data)
|
||||||
|
{
|
||||||
|
GRecMutex *rec_mutex = (GRecMutex *) data;
|
||||||
|
g_assert_false (g_rec_mutex_trylock (rec_mutex));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thread function to check that a recursive mutex given in @data is unlocked */
|
||||||
|
static gpointer
|
||||||
|
rec_mutex_unlocked_thread (gpointer data)
|
||||||
|
{
|
||||||
|
GRecMutex *rec_mutex = (GRecMutex *) data;
|
||||||
|
g_assert_true (g_rec_mutex_trylock (rec_mutex));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_g_rec_mutex_locker (void)
|
||||||
|
{
|
||||||
|
GRecMutex rec_mutex;
|
||||||
|
GThread *thread;
|
||||||
|
|
||||||
|
g_rec_mutex_init (&rec_mutex);
|
||||||
|
|
||||||
|
if (TRUE)
|
||||||
|
{
|
||||||
|
g_autoptr(GRecMutexLocker) val = g_rec_mutex_locker_new (&rec_mutex);
|
||||||
|
|
||||||
|
g_assert_nonnull (val);
|
||||||
|
|
||||||
|
/* Verify that the mutex is actually locked */
|
||||||
|
thread = g_thread_new ("rec mutex locked", rec_mutex_locked_thread, &rec_mutex);
|
||||||
|
g_thread_join (thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that the mutex is unlocked again */
|
||||||
|
thread = g_thread_new ("rec mutex unlocked", rec_mutex_unlocked_thread, &rec_mutex);
|
||||||
|
g_thread_join (thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -536,6 +606,7 @@ main (int argc, gchar *argv[])
|
|||||||
g_test_add_func ("/autoptr/g_thread", test_g_thread);
|
g_test_add_func ("/autoptr/g_thread", test_g_thread);
|
||||||
g_test_add_func ("/autoptr/g_mutex", test_g_mutex);
|
g_test_add_func ("/autoptr/g_mutex", test_g_mutex);
|
||||||
g_test_add_func ("/autoptr/g_mutex_locker", test_g_mutex_locker);
|
g_test_add_func ("/autoptr/g_mutex_locker", test_g_mutex_locker);
|
||||||
|
g_test_add_func ("/autoptr/g_rec_mutex_locker", test_g_rec_mutex_locker);
|
||||||
g_test_add_func ("/autoptr/g_cond", test_g_cond);
|
g_test_add_func ("/autoptr/g_cond", test_g_cond);
|
||||||
g_test_add_func ("/autoptr/g_timer", test_g_timer);
|
g_test_add_func ("/autoptr/g_timer", test_g_timer);
|
||||||
g_test_add_func ("/autoptr/g_time_zone", test_g_time_zone);
|
g_test_add_func ("/autoptr/g_time_zone", test_g_time_zone);
|
||||||
|
Loading…
Reference in New Issue
Block a user