]> git.ozlabs.org Git - ccan-lca-2011.git/blob - ccan/tevent/tevent_util.h
lca2011: hacky import of tevent.
[ccan-lca-2011.git] / ccan / tevent / tevent_util.h
1 #ifndef CCAN_TEVENT_TEVENT_UTIL_H
2 #define CCAN_TEVENT_TEVENT_UTIL_H
3 /*
4    Unix SMB/CIFS implementation.
5
6    Copyright (C) Andrew Tridgell 1998-2010
7    Copyright (C) Jelmer Vernooij 2005
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /* To use these macros you must have a structure containing a next and
24    prev pointer */
25
26 #ifndef _DLINKLIST_H
27 #define _DLINKLIST_H
28
29 /*
30   February 2010 - changed list format to have a prev pointer from the
31   list head. This makes DLIST_ADD_END() O(1) even though we only have
32   one list pointer.
33
34   The scheme is as follows:
35
36      1) with no entries in the list:
37           list_head == NULL
38
39      2) with 1 entry in the list:
40           list_head->next == NULL
41           list_head->prev == list_head
42
43      3) with 2 entries in the list:
44           list_head->next == element2
45           list_head->prev == element2
46           element2->prev == list_head
47           element2->next == NULL
48
49      4) with N entries in the list:
50           list_head->next == element2
51           list_head->prev == elementN
52           elementN->prev == element{N-1}
53           elementN->next == NULL
54
55   This allows us to find the tail of the list by using
56   list_head->prev, which means we can add to the end of the list in
57   O(1) time
58
59
60   Note that the 'type' arguments below are no longer needed, but
61   are kept for now to prevent an incompatible argument change
62  */
63
64
65 /*
66    add an element at the front of a list
67 */
68 #define DLIST_ADD(list, p) \
69 do { \
70         if (!(list)) { \
71                 (p)->prev = (list) = (p);  \
72                 (p)->next = NULL; \
73         } else { \
74                 (p)->prev = (list)->prev; \
75                 (list)->prev = (p); \
76                 (p)->next = (list); \
77                 (list) = (p); \
78         } \
79 } while (0)
80
81 /*
82    remove an element from a list
83    Note that the element doesn't have to be in the list. If it
84    isn't then this is a no-op
85 */
86 #define DLIST_REMOVE(list, p) \
87 do { \
88         if ((p) == (list)) { \
89                 if ((p)->next) (p)->next->prev = (p)->prev; \
90                 (list) = (p)->next; \
91         } else if ((list) && (p) == (list)->prev) {     \
92                 (p)->prev->next = NULL; \
93                 (list)->prev = (p)->prev; \
94         } else { \
95                 if ((p)->prev) (p)->prev->next = (p)->next; \
96                 if ((p)->next) (p)->next->prev = (p)->prev; \
97         } \
98         if ((p) != (list)) (p)->next = (p)->prev = NULL;        \
99 } while (0)
100
101 /*
102    find the head of the list given any element in it.
103    Note that this costs O(N), so you should avoid this macro
104    if at all possible!
105 */
106 #define DLIST_HEAD(p, result_head) \
107 do { \
108        (result_head) = (p); \
109        while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
110 } while(0)
111
112 /* return the last element in the list */
113 #define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
114
115 /* return the previous element in the list. */
116 #define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
117
118 /* insert 'p' after the given element 'el' in a list. If el is NULL then
119    this is the same as a DLIST_ADD() */
120 #define DLIST_ADD_AFTER(list, p, el) \
121 do { \
122         if (!(list) || !(el)) { \
123                 DLIST_ADD(list, p); \
124         } else { \
125                 (p)->prev = (el);   \
126                 (p)->next = (el)->next;         \
127                 (el)->next = (p);               \
128                 if ((p)->next) (p)->next->prev = (p);   \
129                 if ((list)->prev == (el)) (list)->prev = (p); \
130         }\
131 } while (0)
132
133
134 /*
135    add to the end of a list.
136    Note that 'type' is ignored
137 */
138 #define DLIST_ADD_END(list, p, type)                    \
139 do { \
140         if (!(list)) { \
141                 DLIST_ADD(list, p); \
142         } else { \
143                 DLIST_ADD_AFTER(list, p, (list)->prev); \
144         } \
145 } while (0)
146
147 /* promote an element to the from of a list */
148 #define DLIST_PROMOTE(list, p) \
149 do { \
150           DLIST_REMOVE(list, p); \
151           DLIST_ADD(list, p); \
152 } while (0)
153
154 /*
155    demote an element to the end of a list.
156    Note that 'type' is ignored
157 */
158 #define DLIST_DEMOTE(list, p, type)                     \
159 do { \
160         DLIST_REMOVE(list, p); \
161         DLIST_ADD_END(list, p, NULL);           \
162 } while (0)
163
164 /*
165    concatenate two lists - putting all elements of the 2nd list at the
166    end of the first list.
167    Note that 'type' is ignored
168 */
169 #define DLIST_CONCATENATE(list1, list2, type)   \
170 do { \
171         if (!(list1)) { \
172                 (list1) = (list2); \
173         } else { \
174                 (list1)->prev->next = (list2); \
175                 if (list2) { \
176                         void *_tmplist = (void *)(list1)->prev; \
177                         (list1)->prev = (list2)->prev; \
178                         (list2)->prev = _tmplist; \
179                 } \
180         } \
181 } while (0)
182
183 #endif /* _DLINKLIST_H */
184
185 const char **ev_str_list_add(const char **list, const char *s);
186 int ev_set_blocking(int fd, bool set);
187 size_t ev_str_list_length(const char **list);
188
189 /* Defined here so we can build against older talloc versions that don't
190  * have this define yet. */
191 #ifndef TALLOC_FREE
192 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
193 #endif
194
195 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
196
197 #define _PRIVATE_
198 #endif /* CCAN_TEVENT_TEVENT_UTIL_H */