summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-08-21 19:04:32 +0000
committerMark Michelson <mmichelson@digium.com>2012-08-21 19:04:32 +0000
commit89a5ff859d4e6a66c813f5b240d8c9f6ddb119a3 (patch)
tree9a6d125d64f7ff4c011b599218a22372ff8580bb /include
parentdb69da3667955373c06ebae66141c3cd42834fcc (diff)
Add scoped locks to Asterisk.
With the SCOPED_LOCK macro, you can create a variable that locks a specific lock and unlocks the lock when the variable goes out of scope. This is useful for situations where many breaks, continues, returns, or other interruptions would require separate unlock statements. With a scoped lock, these aren't necessary. There are specializations for mutexes, read locks, write locks, ao2 locks, ao2 read locks, ao2 write locks, and channel locks. Each of these is a SCOPED_LOCK at heart though. Review: https://reviewboard.asterisk.org/r/2060 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@371582 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include')
-rw-r--r--include/asterisk/lock.h76
1 files changed, 76 insertions, 0 deletions
diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h
index 943c7ffe6..573fc0c00 100644
--- a/include/asterisk/lock.h
+++ b/include/asterisk/lock.h
@@ -549,6 +549,82 @@ static void __attribute__((destructor)) fini_##rwlock(void) \
#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
#define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
+/*!
+ * \brief Scoped Locks
+ *
+ * Scoped locks provide a way to use RAII locks. In other words,
+ * declaration of a scoped lock will automatically define and lock
+ * the lock. When the lock goes out of scope, it will automatically
+ * be unlocked.
+ *
+ * \example
+ * int some_function(struct ast_channel *chan)
+ * {
+ * SCOPED_LOCK(lock, chan, ast_channel_lock, ast_channel_unlock);
+ *
+ * if (!strcmp(ast_channel_name(chan, "foo")) {
+ * return 0;
+ * }
+ *
+ * return -1;
+ * }
+ *
+ * In the above example, neither return path requires explicit unlocking
+ * of the channel.
+ *
+ * \note
+ * Care should be taken when using SCOPED_LOCKS in conjunction with ao2 objects.
+ * ao2 objects should be unlocked before they are unreffed. Since SCOPED_LOCK runs
+ * once the variable goes out of scope, this can easily lead to situations where the
+ * variable gets unlocked after it is unreffed.
+ *
+ * \param varname The unique name to give to the scoped lock. You are not likely to reference
+ * this outside of the SCOPED_LOCK invocation.
+ * \param lock The variable to lock. This can be anything that can be passed to a locking
+ * or unlocking function.
+ * \param lockfunc The function to call to lock the lock
+ * \param unlockfunc The function to call to unlock the lock
+ */
+#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc) \
+ auto void _dtor_ ## varname (typeof((lock)) * v); \
+ auto void _dtor_ ## varname (typeof((lock)) * v) { unlockfunc(*v); } \
+ typeof((lock)) varname __attribute__((cleanup(_dtor_ ## varname))) = lock; lockfunc((lock))
+
+/*!
+ * \brief scoped lock specialization for mutexes
+ */
+#define SCOPED_MUTEX(varname, lock) SCOPED_LOCK(varname, (lock), ast_mutex_lock, ast_mutex_unlock)
+
+/*!
+ * \brief scoped lock specialization for read locks
+ */
+#define SCOPED_RDLOCK(varname, lock) SCOPED_LOCK(varname, (lock), ast_rwlock_rdlock, ast_rwlock_unlock)
+
+/*!
+ * \brief scoped lock specialization for write locks
+ */
+#define SCOPED_WRLOCK(varname, lock) SCOPED_LOCK(varname, (lock), ast_rwlock_wrlock, ast_rwlock_unlock)
+
+/*!
+ * \brief scoped lock specialization for ao2 mutexes.
+ */
+#define SCOPED_AO2LOCK(varname, obj) SCOPED_LOCK(varname, (obj), ao2_lock, ao2_unlock)
+
+/*!
+ * \brief scoped lock specialization for ao2 read locks.
+ */
+#define SCOPED_AO2RDLOCK(varname, obj) SCOPED_LOCK(varname, (obj), ao2_rdlock, ao2_unlock)
+
+/*!
+ * \brief scoped lock specialization for ao2 write locks.
+ */
+#define SCOPED_AO2WRLOCK(varname, obj) SCOPED_LOCK(varname, (obj), ao2_wrlock, ao2_unlock)
+
+/*!
+ * \brief scoped lock specialization for channels.
+ */
+#define SCOPED_CHANNELLOCK(varname, chan) SCOPED_LOCK(varname, (chan), ast_channel_lock, ast_channel_unlock)
+
#ifndef __CYGWIN__ /* temporary disabled for cygwin */
#define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
#define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t