Kannel: Open Source WAP and SMS gateway  svn-r5335
list.h
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * list.h - generic dynamic list
59  *
60  * This is a generic, dynamic list. Generic means that it stores void pointers
61  * (void *), instead of a more specific data type. This allows storage of
62  * any type of items in the list. The pointers may not be NULL pointers.
63  *
64  * A number of operations are defined for the list: create, destroy,
65  * query of length, inserting and deleting items, getting items, and so on.
66  * See below for a detailed list.
67  *
68  * The list is also thread safe: each single operation is atomic. For
69  * list manipulation that needs to be atomic but uses several single
70  * operations, the list supports locking and unlocking. It is up to the
71  * caller to make sure the list lock is used properly; the implementation
72  * only guarantees the atomicity of single operations.
73  *
74  * The API also has functions for solving typical producer-consumer problems:
75  * the list counts the number of producers it has (they need to register
76  * _and_ unregister explicitly) and has functions for adding a produced
77  * item to the list and removing an item so that it can be consumed. The
78  * consumption function (`gwlist_consume') sleeps, without using processor
79  * time, until there is an item to be consumed or there are no more
80  * producers. Thus, a typical producer would look like this:
81  *
82  * gwlist_add_producer(list);
83  * while ((item = foo()) != NULL)
84  * gwlist_produce(list, item);
85  * gwlist_remove_producer(list);
86  *
87  * and the corresponding consumer would look like this:
88  *
89  * while ((item = gwlist_consume(list)) != NULL)
90  * bar(item);
91  *
92  * There can be any number of producers and consumers at the same time.
93  *
94  * List items are numbered starting with `0'.
95  *
96  * Most list functions can do memory allocations. If these allocations
97  * fail, they will kill the program (they use gwlib/gwmem.c for
98  * memory allocations, and those do the killing). This is not mentioned
99  * explicitly for each function.
100  *
101  * The module prefix is `list' (in any combination of upper and lower case
102  * characters). All externally visible symbols (i.e., those defined by
103  * this header file) start with the prefix.
104  */
105 
106 #ifndef LIST_H
107 #define LIST_H
108 
109 
110 /*
111  * The list type. It is opaque: do not touch it except via the functions
112  * defined in this header.
113  */
114 typedef struct List List;
115 
116 
117 /*
118  * A comparison function for list items. Returns true (non-zero) for
119  * equal, false for non-equal. Gets an item from the list as the first
120  * argument, the pattern as a second argument.
121  */
122 typedef int gwlist_item_matches_t(void *item, void *pattern);
123 
124 
125 /*
126  * A destructor function for list items. Must free all memory associated
127  * with the list item.
128  */
129 typedef void gwlist_item_destructor_t(void *item);
130 
131 
132 /*
133  * Create a list and return a pointer to the list object.
134  */
135 List *gwlist_create_real(void);
136 #define gwlist_create() gw_claim_area(gwlist_create_real())
137 
138 /*
139  * Destroy the list. If `destructor' is not NULL, first destroy all items
140  * by calling it for each item. If it is NULL, the caller is responsible
141  * for destroying items. The caller is also responsible for making sure
142  * that nothing else tries to touch the list from the time the call to
143  * gwlist_destroy starts - this includes the item destructor function.
144  */
145 void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor);
146 
147 
148 /*
149  * Return the number of items in the list. Return 0 if list is NULL.
150  */
151 long gwlist_len(List *list);
152 
153 
154 /*
155  * Add a new item to the end of the list.
156  */
157 void gwlist_append(List *list, void *item);
158 
159 
160 /*
161  * This is similar to gwlist_append(). If the item is *not* present in the
162  * list it is added to the end of the list, otherwise the item is
163  * discarded and *not* added to the list. Hence you can assume that using
164  * this append function you result in a unique item inside the list.
165  */
166 void gwlist_append_unique(List *list, void *item, gwlist_item_matches_t *cmp);
167 
168 
169 /*
170  * Insert an item into the list so that it becomes item number `pos'.
171  */
172 void gwlist_insert(List *list, long pos, void *item);
173 
174 
175 /*
176  * Delete items from the list. Note that this does _not_ free the memory
177  * for the items, they are just dropped from the list.
178  */
179 void gwlist_delete(List *list, long pos, long count);
180 
181 
182 /*
183  * Delete all items from the list that match `pattern'. Like gwlist_delete,
184  * the items are removed from the list, but are not destroyed themselves.
185  * Return the number of items deleted.
186  */
187 long gwlist_delete_matching(List *list, void *pat, gwlist_item_matches_t *cmp);
188 
189 
190 /*
191  * Delete all items from the list whose pointer value is exactly `item'.
192  * Return the number of items deleted.
193  */
194 long gwlist_delete_equal(List *list, void *item);
195 
196 
197 /*
198  * Return the item at position `pos'.
199  */
200 void *gwlist_get(List *list, long pos);
201 
202 
203 /*
204  * Remove and return the first item in the list. Return NULL if list is
205  * empty. Note that unlike gwlist_consume, this won't sleep until there is
206  * something in the list.
207  */
208 void *gwlist_extract_first(List *list);
209 
210 
211 /*
212  * Create a new list with items from `list' that match a pattern. The items
213  * are removed from `list'. Return NULL if no matching items are found.
214  * Note that unlike gwlist_consume, this won't sleep until there is
215  * something in the list.
216  */
217 List *gwlist_extract_matching(List *list, void *pat, gwlist_item_matches_t *cmp);
218 
219 
220 /*
221  * Lock the list. This protects the list from other threads that also
222  * lock the list with gwlist_lock, but not from threads that do not.
223  * (This is intentional.)
224  */
225 void gwlist_lock(List *list);
226 
227 
228 /*
229  * Unlock the list lock locked by gwlist_lock. Only the owner of the lock
230  * may unlock it (although this might not be checked).
231  */
232 void gwlist_unlock(List *list);
233 
234 
235 /*
236  * Sleep until the list is non-empty. Note that after the thread awakes
237  * another thread may already have emptied the list again. Those who wish
238  * to use this function need to be very careful with gwlist_lock and
239  * gwlist_unlock.
240  */
242 
243 
244 /*
245  * Register a new producer to the list.
246  */
247 void gwlist_add_producer(List *list);
248 
249 /*
250  * Return the current number of producers for the list
251  */
252 int gwlist_producer_count(List *list);
253 
254 /*
255  * Remove a producer from the list. If the number of producers drops to
256  * zero, all threads sleeping in gwlist_consume will awake and return NULL.
257  */
258 void gwlist_remove_producer(List *list);
259 
260 
261 /*
262  * Add an item to the list. This equivalent to gwlist_append, but may be
263  * easier to remember.
264  */
265 void gwlist_produce(List *list, void *item);
266 
267 
268 /*
269  * Return the current number of consumers for the list
270  */
271 int gwlist_consumer_count(List *list);
272 
273 
274 /*
275  * Remove an item from the list, or return NULL if the list was empty
276  * and there were no producers. If the list is empty but there are
277  * producers, sleep until there is something to return.
278  */
279 void *gwlist_consume(List *list);
280 
281 
282 /*
283  * Remove an item from the list, or return NULL if the list was empty
284  * and there were no producers. If the list is empty but there are
285  * producers, sleep until there is something to return or timeout occur.
286  */
287 void *gwlist_timed_consume(List *list, long sec);
288 
289 
290 /*
291  * Search the list for a particular item. If not found, return NULL. If found,
292  * return the list element. Compare items to search pattern with
293  * `cmp(item, pattern)'. If the function returns non-zero, the items are
294  * equal.
295  */
296 void *gwlist_search(List *list, void *pattern, gwlist_item_matches_t *cmp);
297 
298 
299 /*
300  * Search the list for all items matching a pattern. If not found, return
301  * NULL. If found, return a list with the matching elements. Compare items
302  * to search pattern with `cmp(item, pattern)'. If the function returns
303  * non-zero, the items are equal.
304  */
305 List *gwlist_search_all(List *list, void *pattern, gwlist_item_matches_t *cmp);
306 
307 
308 /*
309  * Search the list for the first equal item. If not found, return -1. If found
310  * return position.
311  */
312 long gwlist_search_equal(List *list, void *item);
313 
314 
315 /*
316  * Sort the list with qsort.
317  * if you have a list that you feed like that:
318  * Msg *message;
319  * gwlist_add(mylist, message);
320  * a function that could sort messages by their data length would look like that:
321  * int sort_by_messagelength(void* first_msg_pp, void* second_msg_pp)
322  * {
323  * Msg *first_msg=(Msg*)first_msg_pp;
324  * Msg *second_msg=(Msg*)second_msg_pp;
325  * return octstr_len(first_msg->sms.msgdata) - octstr_len(second_msg->sms.msgdata);
326  * }
327  */
328 void gwlist_sort(List *list, int(*cmp)(const void *, const void *));
329 
330 #endif
List * gwlist_create_real(void)
Definition: list.c:127
void gwlist_insert(List *list, long pos, void *item)
Definition: list.c:214
void gwlist_lock(List *list)
Definition: list.c:347
void gwlist_add_producer(List *list)
Definition: list.c:383
long gwlist_delete_matching(List *list, void *pat, gwlist_item_matches_t *cmp)
Definition: list.c:240
void * gwlist_extract_first(List *list)
Definition: list.c:305
List * gwlist_search_all(List *list, void *pattern, gwlist_item_matches_t *cmp)
long gwlist_delete_equal(List *list, void *item)
Definition: list.c:266
void * gwlist_consume(List *list)
Definition: list.c:427
void gwlist_append(List *list, void *item)
Definition: list.c:179
long gwlist_len(List *list)
Definition: list.c:166
void gwlist_item_destructor_t(void *item)
Definition: list.h:129
List * gwlist_extract_matching(List *list, void *pat, gwlist_item_matches_t *cmp)
Definition: list.c:322
void gwlist_append_unique(List *list, void *item, gwlist_item_matches_t *cmp)
void gwlist_produce(List *list, void *item)
Definition: list.c:411
int gwlist_producer_count(List *list)
Definition: list.c:391
void * gwlist_get(List *list, long pos)
Definition: list.c:292
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
void gwlist_sort(List *list, int(*cmp)(const void *, const void *))
Definition: list.c:576
void * gwlist_search(List *list, void *pattern, gwlist_item_matches_t *cmp)
long gwlist_search_equal(List *list, void *item)
Definition: list.c:534
void * gwlist_timed_consume(List *list, long sec)
Definition: list.c:453
int gwlist_wait_until_nonempty(List *list)
Definition: list.c:361
int gwlist_item_matches_t(void *item, void *pattern)
Definition: list.h:122
int gwlist_consumer_count(List *list)
Definition: list.c:417
void gwlist_delete(List *list, long pos, long count)
Definition: list.c:232
void gwlist_remove_producer(List *list)
Definition: list.c:401
Definition: list.c:102
void gwlist_unlock(List *list)
Definition: list.c:354
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.