Add AST_RWLIST_* set of macros which implement linked lists using read/write locks...
authorJoshua Colp <jcolp@digium.com>
Thu, 2 Nov 2006 17:56:33 +0000 (17:56 +0000)
committerJoshua Colp <jcolp@digium.com>
Thu, 2 Nov 2006 17:56:33 +0000 (17:56 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@46967 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/linkedlists.h

index 865fafe..268f827 100644 (file)
 */
 #define AST_LIST_LOCK(head)                                            \
        ast_mutex_lock(&(head)->lock) 
+
+/*!
+  \brief Write locks a list.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place an exclusive write lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_WRLOCK(head)                                         \
+        ast_rwlock_wrlock(&(head)->lock)
+
+/*!
+  \brief Read locks a list.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place a read lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_RDLOCK(head)                                         \
+        ast_rwlock_rdlock(&(head)->lock)
        
 /*!
   \brief Locks a list, without blocking if the list is locked.
 */
 #define AST_LIST_TRYLOCK(head)                                         \
        ast_mutex_trylock(&(head)->lock) 
+
+/*!
+  \brief Write locks a list, without blocking if the list is locked.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place an exclusive write lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_TRYWRLOCK(head)                                      \
+        ast_rwlock_trywrlock(&(head)->lock)
+
+/*!
+  \brief Read locks a list, without blocking if the list is locked.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to place a read lock in the
+  list head structure pointed to by head.
+  Returns non-zero on success, 0 on failure
+*/
+#define AST_RWLIST_TRYRDLOCK(head)                                      \
+        ast_rwlock_tryrdlock(&(head)->lock)
        
 /*!
   \brief Attempts to unlock a list.
        ast_mutex_unlock(&(head)->lock)
 
 /*!
+  \brief Attempts to unlock a read/write based list.
+  \param head This is a pointer to the list head structure
+
+  This macro attempts to remove a read or write lock from the
+  list head structure pointed to by head. If the list
+  was not locked by this thread, this macro has no effect.
+*/
+#define AST_RWLIST_UNLOCK(head)                                         \
+        ast_rwlock_unlock(&(head)->lock)
+
+/*!
   \brief Defines a structure to be used to hold a list of specified type.
   \param name This will be the name of the defined structure.
   \param type This is the type of each list entry.
@@ -87,6 +142,32 @@ struct name {                                                               \
 }
 
 /*!
+  \brief Defines a structure to be used to hold a read/write list of specified type.
+  \param name This will be the name of the defined structure.
+  \param type This is the type of each list entry.
+
+  This macro creates a structure definition that can be used
+  to hold a list of the entries of type \a type. It does not actually
+  declare (allocate) a structure; to do that, either follow this
+  macro with the desired name of the instance you wish to declare,
+  or use the specified \a name to declare instances elsewhere.
+
+  Example usage:
+  \code
+  static AST_RWLIST_HEAD(entry_list, entry) entries;
+  \endcode
+
+  This would define \c struct \c entry_list, and declare an instance of it named
+  \a entries, all intended to hold a list of type \c struct \c entry.
+*/
+#define AST_RWLIST_HEAD(name, type)                                     \
+struct name {                                                           \
+        struct type *first;                                             \
+        struct type *last;                                              \
+        ast_rwlock_t lock;                                              \
+}
+
+/*!
   \brief Defines a structure to be used to hold a list of specified type (with no lock).
   \param name This will be the name of the defined structure.
   \param type This is the type of each list entry.
@@ -121,6 +202,15 @@ struct name {                                                              \
        }
 
 /*!
+  \brief Defines initial values for a declaration of AST_RWLIST_HEAD
+*/
+#define AST_RWLIST_HEAD_INIT_VALUE      {               \
+        .first = NULL,                                  \
+        .last = NULL,                                   \
+        .lock = AST_RWLOCK_INIT_VALUE,                  \
+        }
+
+/*!
   \brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
 */
 #define AST_LIST_HEAD_NOLOCK_INIT_VALUE        {       \
@@ -171,6 +261,48 @@ struct name {                                                              \
 #endif
 
 /*!
+  \brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
+  \param name This will be the name of the defined structure.
+  \param type This is the type of each list entry.
+
+  This macro creates a structure definition that can be used
+  to hold a list of the entries of type \a type, and allocates an instance
+  of it, initialized to be empty.
+
+  Example usage:
+  \code
+  static AST_RWLIST_HEAD_STATIC(entry_list, entry);
+  \endcode
+
+  This would define \c struct \c entry_list, intended to hold a list of
+  type \c struct \c entry.
+*/
+#ifndef AST_RWLOCK_INIT_VALUE
+#define AST_RWLIST_HEAD_STATIC(name, type)                              \
+struct name {                                                           \
+        struct type *first;                                             \
+        struct type *last;                                              \
+        ast_rwlock_t lock;                                              \
+} name;                                                                 \
+static void  __attribute__ ((constructor)) init_##name(void)            \
+{                                                                       \
+        AST_RWLIST_HEAD_INIT(&name);                                    \
+}                                                                       \
+static void  __attribute__ ((destructor)) fini_##name(void)             \
+{                                                                       \
+        AST_RWLIST_HEAD_DESTROY(&name);                                 \
+}                                                                       \
+struct __dummy_##name
+#else
+#define AST_RWLIST_HEAD_STATIC(name, type)                              \
+struct name {                                                           \
+        struct type *first;                                             \
+        struct type *last;                                              \
+        ast_rwlock_t lock;                                              \
+} name = AST_RWLIST_HEAD_INIT_VALUE
+#endif
+
+/*!
   \brief Defines a structure to be used to hold a list of specified type, statically initialized.
 
   This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
@@ -196,6 +328,20 @@ struct name {                                                              \
 } while (0)
 
 /*!
+  \brief Initializes an rwlist head structure with a specified first entry.
+  \param head This is a pointer to the list head structure
+  \param entry pointer to the list entry that will become the head of the list
+
+  This macro initializes a list head structure by setting the head
+  entry to the supplied value and recreating the embedded lock.
+*/
+#define AST_RWLIST_HEAD_SET(head, entry) do {                           \
+        (head)->first = (entry);                                        \
+        (head)->last = (entry);                                         \
+        ast_rwlock_init(&(head)->lock);                                 \
+} while (0)
+
+/*!
   \brief Initializes a list head structure with a specified first entry.
   \param head This is a pointer to the list head structure
   \param entry pointer to the list entry that will become the head of the list
@@ -229,6 +375,8 @@ struct name {                                                               \
 struct {                                                               \
        struct type *next;                                              \
 }
+
+#define AST_RWLIST_ENTRY AST_LIST_ENTRY
  
 /*!
   \brief Returns the first entry contained in a list.
@@ -236,12 +384,16 @@ struct {                                                          \
  */
 #define        AST_LIST_FIRST(head)    ((head)->first)
 
+#define AST_RWLIST_FIRST AST_LIST_FIRST
+
 /*!
   \brief Returns the last entry contained in a list.
   \param head This is a pointer to the list head structure
  */
 #define        AST_LIST_LAST(head)     ((head)->last)
 
+#define AST_RWLIST_LAST AST_LIST_LAST
+
 /*!
   \brief Returns the next entry in the list after the given entry.
   \param elm This is a pointer to the current entry.
@@ -250,6 +402,8 @@ struct {                                                            \
 */
 #define AST_LIST_NEXT(elm, field)      ((elm)->field.next)
 
+#define AST_RWLIST_NEXT AST_LIST_NEXT
+
 /*!
   \brief Checks whether the specified list contains any entries.
   \param head This is a pointer to the list head structure
@@ -258,6 +412,8 @@ struct {                                                            \
  */
 #define        AST_LIST_EMPTY(head)    (AST_LIST_FIRST(head) == NULL)
 
+#define AST_RWLIST_EMPTY AST_LIST_EMPTY
+
 /*!
   \brief Loops over (traverses) the entries in a list.
   \param head This is a pointer to the list head structure
@@ -297,6 +453,8 @@ struct {                                                            \
 #define AST_LIST_TRAVERSE(head,var,field)                              \
        for((var) = (head)->first; (var); (var) = (var)->field.next)
 
+#define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
+
 /*!
   \brief Loops safely over (traverses) the entries in a list.
   \param head This is a pointer to the list head structure
@@ -342,6 +500,8 @@ struct {                                                            \
             __list_next = (var) ? (var)->field.next : NULL                             \
            )
 
+#define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
+
 /*!
   \brief Removes the \a current entry from a list during a traversal.
   \param head This is a pointer to the list head structure
@@ -363,6 +523,8 @@ struct {                                                            \
        if (!__list_next)                                                               \
                (head)->last = __list_prev;
 
+#define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
+
 /*!
   \brief Inserts a list entry before the current entry during a traversal.
   \param head This is a pointer to the list head structure
@@ -384,11 +546,15 @@ struct {                                                          \
        __new_prev = (elm);                                             \
 } while (0)
 
+#define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
+
 /*!
   \brief Closes a safe loop traversal block.
  */
 #define AST_LIST_TRAVERSE_SAFE_END  }
 
+#define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
+
 /*!
   \brief Initializes a list head structure.
   \param head This is a pointer to the list head structure
@@ -403,6 +569,19 @@ struct {                                                           \
 }
 
 /*!
+  \brief Initializes an rwlist head structure.
+  \param head This is a pointer to the list head structure
+
+  This macro initializes a list head structure by setting the head
+  entry to \a NULL (empty list) and recreating the embedded lock.
+*/
+#define AST_RWLIST_HEAD_INIT(head) {                                    \
+        (head)->first = NULL;                                           \
+        (head)->last = NULL;                                            \
+        ast_rwlock_init(&(head)->lock);                                 \
+}
+
+/*!
   \brief Destroys a list head structure.
   \param head This is a pointer to the list head structure
 
@@ -417,6 +596,20 @@ struct {                                                           \
 }
 
 /*!
+  \brief Destroys an rwlist head structure.
+  \param head This is a pointer to the list head structure
+
+  This macro destroys a list head structure by setting the head
+  entry to \a NULL (empty list) and destroying the embedded lock.
+  It does not free the structure from memory.
+*/
+#define AST_RWLIST_HEAD_DESTROY(head) {                                 \
+        (head)->first = NULL;                                           \
+        (head)->last = NULL;                                            \
+        ast_rwlock_destroy(&(head)->lock);                              \
+}
+
+/*!
   \brief Initializes a list head structure.
   \param head This is a pointer to the list head structure
 
@@ -445,6 +638,8 @@ struct {                                                            \
                (head)->last = (elm);                                   \
 } while (0)
 
+#define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
+
 /*!
   \brief Inserts a list entry at the head of a list.
   \param head This is a pointer to the list head structure
@@ -459,6 +654,8 @@ struct {                                                            \
                        (head)->last = (elm);                           \
 } while (0)
 
+#define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
+
 /*!
   \brief Appends a list entry to the tail of a list.
   \param head This is a pointer to the list head structure
@@ -480,6 +677,8 @@ struct {                                                            \
       }                                                                        \
 } while (0)
 
+#define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
+
 /*!
   \brief Appends a whole list to the tail of a list.
   \param head This is a pointer to the list head structure
@@ -497,6 +696,8 @@ struct {                                                            \
       }                                                                        \
 } while (0)
 
+#define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
+
 /*!
   \brief Removes and returns the head entry from a list.
   \param head This is a pointer to the list head structure
@@ -517,6 +718,8 @@ struct {                                                            \
                cur;                                                    \
        })
 
+#define AST_RWLIST_REMOVE_HEAD AST_LIST_REMOVE_HEAD
+
 /*!
   \brief Removes a specific entry from a list.
   \param head This is a pointer to the list head structure
@@ -543,4 +746,6 @@ struct {                                                            \
         (elm)->field.next = NULL;                                       \
 } while (0)
 
+#define AST_RWLIST_REMOVE AST_LIST_REMOVE
+
 #endif /* _ASTERISK_LINKEDLISTS_H */