00001 /* ==================================================================== 00002 * The Kannel Software License, Version 1.0 00003 * 00004 * Copyright (c) 2001-2008 Kannel Group 00005 * Copyright (c) 1998-2001 WapIT Ltd. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in 00017 * the documentation and/or other materials provided with the 00018 * distribution. 00019 * 00020 * 3. The end-user documentation included with the redistribution, 00021 * if any, must include the following acknowledgment: 00022 * "This product includes software developed by the 00023 * Kannel Group (http://www.kannel.org/)." 00024 * Alternately, this acknowledgment may appear in the software itself, 00025 * if and wherever such third-party acknowledgments normally appear. 00026 * 00027 * 4. The names "Kannel" and "Kannel Group" must not be used to 00028 * endorse or promote products derived from this software without 00029 * prior written permission. For written permission, please 00030 * contact org@kannel.org. 00031 * 00032 * 5. Products derived from this software may not be called "Kannel", 00033 * nor may "Kannel" appear in their name, without prior written 00034 * permission of the Kannel Group. 00035 * 00036 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 00037 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00038 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00039 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 00040 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 00041 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00042 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 00043 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00044 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 00045 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 00046 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00047 * ==================================================================== 00048 * 00049 * This software consists of voluntary contributions made by many 00050 * individuals on behalf of the Kannel Group. For more information on 00051 * the Kannel Group, please see <http://www.kannel.org/>. 00052 * 00053 * Portions of this software are based upon software originally written at 00054 * WapIT Ltd., Helsinki, Finland for the Kannel project. 00055 */ 00056 00057 /* 00058 * list.h - generic dynamic list 00059 * 00060 * This is a generic, dynamic list. Generic means that it stores void pointers 00061 * (void *), instead of a more specific data type. This allows storage of 00062 * any type of items in the list. The pointers may not be NULL pointers. 00063 * 00064 * A number of operations are defined for the list: create, destroy, 00065 * query of length, inserting and deleting items, getting items, and so on. 00066 * See below for a detailed list. 00067 * 00068 * The list is also thread safe: each single operation is atomic. For 00069 * list manipulation that needs to be atomic but uses several single 00070 * operations, the list supports locking and unlocking. It is up to the 00071 * caller to make sure the list lock is used properly; the implementation 00072 * only guarantees the atomicity of single operations. 00073 * 00074 * The API also has functions for solving typical producer-consumer problems: 00075 * the list counts the number of producers it has (they need to register 00076 * _and_ unregister explicitly) and has functions for adding a produced 00077 * item to the list and removing an item so that it can be consumed. The 00078 * consumption function (`gwlist_consume') sleeps, without using processor 00079 * time, until there is an item to be consumed or there are no more 00080 * producers. Thus, a typical producer would look like this: 00081 * 00082 * gwlist_add_producer(list); 00083 * while ((item = foo()) != NULL) 00084 * gwlist_produce(list, item); 00085 * gwlist_remove_producer(list); 00086 * 00087 * and the corresponding consumer would look like this: 00088 * 00089 * while ((item = gwlist_consume(list)) != NULL) 00090 * bar(item); 00091 * 00092 * There can be any number of producers and consumers at the same time. 00093 * 00094 * List items are numbered starting with `0'. 00095 * 00096 * Most list functions can do memory allocations. If these allocations 00097 * fail, they will kill the program (they use gwlib/gwmem.c for 00098 * memory allocations, and those do the killing). This is not mentioned 00099 * explicitly for each function. 00100 * 00101 * The module prefix is `list' (in any combination of upper and lower case 00102 * characters). All externally visible symbols (i.e., those defined by 00103 * this header file) start with the prefix. 00104 */ 00105 00106 #ifndef LIST_H 00107 #define LIST_H 00108 00109 00110 /* 00111 * The list type. It is opaque: do not touch it except via the functions 00112 * defined in this header. 00113 */ 00114 typedef struct List List; 00115 00116 00117 /* 00118 * A comparison function for list items. Returns true (non-zero) for 00119 * equal, false for non-equal. Gets an item from the list as the first 00120 * argument, the pattern as a second argument. 00121 */ 00122 typedef int gwlist_item_matches_t(void *item, void *pattern); 00123 00124 00125 /* 00126 * A destructor function for list items. Must free all memory associated 00127 * with the list item. 00128 */ 00129 typedef void gwlist_item_destructor_t(void *item); 00130 00131 00132 /* 00133 * Create a list and return a pointer to the list object. 00134 */ 00135 List *gwlist_create_real(void); 00136 #define gwlist_create() gw_claim_area(gwlist_create_real()) 00137 00138 /* 00139 * Destroy the list. If `destructor' is not NULL, first destroy all items 00140 * by calling it for each item. If it is NULL, the caller is responsible 00141 * for destroying items. The caller is also responsible for making sure 00142 * that nothing else tries to touch the list from the time the call to 00143 * gwlist_destroy starts - this includes the item destructor function. 00144 */ 00145 void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor); 00146 00147 00148 /* 00149 * Return the number of items in the list. Return 0 if list is NULL. 00150 */ 00151 long gwlist_len(List *list); 00152 00153 00154 /* 00155 * Add a new item to the end of the list. 00156 */ 00157 void gwlist_append(List *list, void *item); 00158 00159 00160 /* 00161 * This is similar to gwlist_append(). If the item is *not* present in the 00162 * list it is added to the end of the list, otherwise the item is 00163 * discarded and *not* added to the list. Hence you can assume that using 00164 * this append function you result in a unique item inside the list. 00165 */ 00166 void gwlist_append_unique(List *list, void *item, gwlist_item_matches_t *cmp); 00167 00168 00169 /* 00170 * Insert an item into the list so that it becomes item number `pos'. 00171 */ 00172 void gwlist_insert(List *list, long pos, void *item); 00173 00174 00175 /* 00176 * Delete items from the list. Note that this does _not_ free the memory 00177 * for the items, they are just dropped from the list. 00178 */ 00179 void gwlist_delete(List *list, long pos, long count); 00180 00181 00182 /* 00183 * Delete all items from the list that match `pattern'. Like gwlist_delete, 00184 * the items are removed from the list, but are not destroyed themselves. 00185 * Return the number of items deleted. 00186 */ 00187 long gwlist_delete_matching(List *list, void *pat, gwlist_item_matches_t *cmp); 00188 00189 00190 /* 00191 * Delete all items from the list whose pointer value is exactly `item'. 00192 * Return the number of items deleted. 00193 */ 00194 long gwlist_delete_equal(List *list, void *item); 00195 00196 00197 /* 00198 * Return the item at position `pos'. 00199 */ 00200 void *gwlist_get(List *list, long pos); 00201 00202 00203 /* 00204 * Remove and return the first item in the list. Return NULL if list is 00205 * empty. Note that unlike gwlist_consume, this won't sleep until there is 00206 * something in the list. 00207 */ 00208 void *gwlist_extract_first(List *list); 00209 00210 00211 /* 00212 * Create a new list with items from `list' that match a pattern. The items 00213 * are removed from `list'. Return NULL if no matching items are found. 00214 * Note that unlike gwlist_consume, this won't sleep until there is 00215 * something in the list. 00216 */ 00217 List *gwlist_extract_matching(List *list, void *pat, gwlist_item_matches_t *cmp); 00218 00219 00220 /* 00221 * Lock the list. This protects the list from other threads that also 00222 * lock the list with gwlist_lock, but not from threads that do not. 00223 * (This is intentional.) 00224 */ 00225 void gwlist_lock(List *list); 00226 00227 00228 /* 00229 * Unlock the list lock locked by gwlist_lock. Only the owner of the lock 00230 * may unlock it (although this might not be checked). 00231 */ 00232 void gwlist_unlock(List *list); 00233 00234 00235 /* 00236 * Sleep until the list is non-empty. Note that after the thread awakes 00237 * another thread may already have emptied the list again. Those who wish 00238 * to use this function need to be very careful with gwlist_lock and 00239 * gwlist_unlock. 00240 */ 00241 int gwlist_wait_until_nonempty(List *list); 00242 00243 00244 /* 00245 * Register a new producer to the list. 00246 */ 00247 void gwlist_add_producer(List *list); 00248 00249 /* 00250 * Return the current number of producers for the list 00251 */ 00252 int gwlist_producer_count(List *list); 00253 00254 /* 00255 * Remove a producer from the list. If the number of producers drops to 00256 * zero, all threads sleeping in gwlist_consume will awake and return NULL. 00257 */ 00258 void gwlist_remove_producer(List *list); 00259 00260 00261 /* 00262 * Add an item to the list. This equivalent to gwlist_append, but may be 00263 * easier to remember. 00264 */ 00265 void gwlist_produce(List *list, void *item); 00266 00267 00268 /* 00269 * Remove an item from the list, or return NULL if the list was empty 00270 * and there were no producers. If the list is empty but there are 00271 * producers, sleep until there is something to return. 00272 */ 00273 void *gwlist_consume(List *list); 00274 00275 00276 /* 00277 * Remove an item from the list, or return NULL if the list was empty 00278 * and there were no producers. If the list is empty but there are 00279 * producers, sleep until there is something to return or timeout occur. 00280 */ 00281 void *gwlist_timed_consume(List *list, long sec); 00282 00283 00284 /* 00285 * Search the list for a particular item. If not found, return NULL. If found, 00286 * return the list element. Compare items to search pattern with 00287 * `cmp(item, pattern)'. If the function returns non-zero, the items are 00288 * equal. 00289 */ 00290 void *gwlist_search(List *list, void *pattern, gwlist_item_matches_t *cmp); 00291 00292 00293 /* 00294 * Search the list for all items matching a pattern. If not found, return 00295 * NULL. If found, return a list with the matching elements. Compare items 00296 * to search pattern with `cmp(item, pattern)'. If the function returns 00297 * non-zero, the items are equal. 00298 */ 00299 List *gwlist_search_all(List *list, void *pattern, gwlist_item_matches_t *cmp); 00300 00301 00302 /* 00303 * Sort the list with qsort. 00304 * if you have a list that you feed like that: 00305 * Msg *message; 00306 * gwlist_add(mylist, message); 00307 * a function that could sort messages by their data length would look like that: 00308 * int sort_by_messagelength(void* first_msg_pp, void* second_msg_pp) 00309 * { 00310 * Msg *first_msg=*(Msg**)first_msg_pp; 00311 * Msg *second_msg=*(Msg**)second_msg_pp; 00312 * return octstr_len(first_msg->sms.msgdata) - octstr_len(second_msg->sms.msgdata); 00313 * } 00314 */ 00315 void gwlist_sort(List *list, int(*cmp)(const void *, const void *)); 00316 00317 #endif