[glib/wip/kalev/recursive-mutex-locker: 21/22] Add GRecMutexLocker
- From: Kalev Lember <klember src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/kalev/recursive-mutex-locker: 21/22] Add GRecMutexLocker
- Date: Fri, 14 Dec 2018 18:23:52 +0000 (UTC)
commit 10ed2d926f5f770261ce76fc08f53599b295b100
Author: Kalev Lember <klember redhat com>
Date: Wed Dec 12 12:03:13 2018 +0100
Add GRecMutexLocker
This is the same as GMutexLocker, just for recursive mutexes.
docs/reference/glib/glib-sections.txt | 5 +++
glib/glib-autocleanups.h | 1 +
glib/gthread.h | 69 +++++++++++++++++++++++++++++++++++
glib/tests/autoptr.c | 43 ++++++++++++++++++++++
4 files changed, 118 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 1369012ce..20dd4cc41 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -730,6 +730,11 @@ g_rec_mutex_lock
g_rec_mutex_trylock
g_rec_mutex_unlock
+<SUBSECTION>
+GRecMutexLocker
+g_rec_mutex_locker_new
+g_rec_mutex_locker_free
+
<SUBSECTION>
GRWLock
g_rw_lock_init
diff --git a/glib/glib-autocleanups.h b/glib/glib-autocleanups.h
index ce1690b78..d89c8d2fe 100644
--- a/glib/glib-autocleanups.h
+++ b/glib/glib-autocleanups.h
@@ -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_AUTO_CLEANUP_CLEAR_FUNC(GMutex, g_mutex_clear)
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_AUTOPTR_CLEANUP_FUNC(GTimer, g_timer_destroy)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GTimeZone, g_time_zone_unref)
diff --git a/glib/gthread.h b/glib/gthread.h
index 3d765c2c2..80b0ef99b 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -336,6 +336,75 @@ g_mutex_locker_free (GMutexLocker *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
#endif /* __G_THREAD_H__ */
diff --git a/glib/tests/autoptr.c b/glib/tests/autoptr.c
index 5b3bce71c..076acced7 100644
--- a/glib/tests/autoptr.c
+++ b/glib/tests/autoptr.c
@@ -344,6 +344,48 @@ test_g_mutex_locker (void)
}
}
+/* 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
test_g_cond (void)
{
@@ -536,6 +578,7 @@ main (int argc, gchar *argv[])
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_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_timer", test_g_timer);
g_test_add_func ("/autoptr/g_time_zone", test_g_time_zone);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]