Fix linked lists tail (bug #951)
[asterisk/asterisk.git] / include / asterisk / linkedlists.h
1 #ifndef ASTERISK_LINKEDLISTS_H
2 #define ASTERISK_LINKEDLISTS_H
3
4 #include <pthread.h>
5 #include <asterisk/lock.h>
6
7 #define AST_LIST_LOCK(head)                                             \
8         ast_mutex_lock(&head->lock) 
9         
10 #define AST_LIST_UNLOCK(head)                                           \
11         ast_mutex_unlock(&head->lock)
12
13 #define AST_LIST_HEAD(name, type)                                       \
14 struct name {                                                           \
15         struct type *first;                                             \
16         ast_mutex_t lock;                                               \
17 }
18
19 #define AST_LIST_HEAD_INITIALIZER(head)                                 \
20         { NULL, AST_MUTEX_INITIALIZER }
21         
22 #define AST_LIST_HEAD_SET(head,entry) do {                              \
23         (head)->first=(entry);                                          \
24         ast_pthread_mutex_init(&(head)->lock,NULL);                             \
25 } while (0)
26
27 #define AST_LIST_ENTRY(type)                                            \
28 struct {                                                                \
29         struct type *next;                                              \
30 }
31  
32 #define AST_LIST_FIRST(head)    ((head)->first)
33
34 #define AST_LIST_NEXT(elm, field)       ((elm)->field.next)
35
36 #define AST_LIST_EMPTY(head)    (AST_LIST_FIRST(head) == NULL)
37
38 #define AST_LIST_TRAVERSE(head,var,field)                               \
39         for((var) = (head)->first; (var); (var) = (var)->field.next)
40
41 #define AST_LIST_HEAD_INIT(head) {                                              \
42         (head)->first = NULL;                                           \
43         ast_pthread_mutex_init(&(head)->lock,NULL);                             \
44 }
45
46 #define AST_LIST_INSERT_AFTER(listelm, elm, field) do {         \
47         (elm)->field.next = (listelm)->field.next;                      \
48         (listelm)->field.next = (elm);                          \
49 } while (0)
50
51 #define AST_LIST_INSERT_HEAD(head, elm, field) do {                     \
52                 (elm)->field.next = (head)->first;                      \
53                 (head)->first = (elm);                                  \
54 } while (0)
55
56 #define AST_LIST_INSERT_TAIL(head, elm, type, field) do {             \
57       struct type *curelm = (head)->first;                            \
58       if(!curelm) {                                                   \
59               AST_LIST_INSERT_HEAD(head, elm, field);                 \
60       } else {                                                        \
61               while ( curelm->field.next!=NULL ) {                    \
62                       curelm=curelm->field.next;                      \
63               }                                                       \
64               AST_LIST_INSERT_AFTER(curelm,elm,field);                \
65       }                                                               \
66 } while (0)
67
68
69 #define AST_LIST_REMOVE_HEAD(head, field) do {                                  \
70                 (head)->first = (head)->first->field.next;                      \
71         } while (0)
72
73 #define AST_LIST_REMOVE(head, elm, type, field) do {                    \
74         if ((head)->first == (elm)) {                                   \
75                 AST_LIST_REMOVE_HEAD((head), field);                    \
76         }                                                               \
77         else {                                                          \
78                 struct type *curelm = (head)->first;                    \
79                 while( curelm->field.next != (elm) )                    \
80                         curelm = curelm->field.next;                    \
81                 curelm->field.next =                                    \
82                     curelm->field.next->field.next;                     \
83         }                                                               \
84 } while (0)
85
86 #endif