X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcdlist.h;h=a27aaad41ca86fd5f9139a986e53fe3bf10e8322;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=d205ede0a9a1a55e91e05024edd097ff441a0efa;hpb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;p=silc.git diff --git a/lib/silcutil/silcdlist.h b/lib/silcutil/silcdlist.h index d205ede0..a27aaad4 100644 --- a/lib/silcutil/silcdlist.h +++ b/lib/silcutil/silcdlist.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2005 Pekka Riikonen + Copyright (C) 2000 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,16 +27,29 @@ * DESCRIPTION * * SILC Dynamic List API can be used to add opaque contexts to list that - * will automatically allocate list entries. Normal SILC List API cannot + * will automatically allocate list entries. The simpler SilcList cannot * be used for this purpose because in that case the context passed to the * list must be defined as list structure already. This is not the case in - * SilcDList. + * SilcDList. But SilcDList is a bit slower than SilcList because it + * requires memory allocation when adding new entries to the list. * - * This is slower than SilcList because this requires one extra memory - * allocation when adding new entries to the list. The context is probably - * allocated already and the new list entry requires one additional memory - * allocation. The memory allocation and freeing is done automatically in - * the API and does not show to the caller. + * SILC Dynamic List is not thread-safe. If the same list context must be + * used in multithreaded environment concurrency control must be employed. + * + * EXAMPLE + * + * SilcDList list = silc_dlist_init(); + * + * silc_dlist_add(list, entry1); + * silc_dlist_add(list, entry2); + * + * // Traverse the list from the beginning to the end + * silc_dlist_start(list) + * while ((entry = silc_dlist_get(list)) != SILC_LIST_END) { + * ... + * } + * + * silc_dlist_uninit(list); * ***/ @@ -52,14 +65,13 @@ * Application defines this object and adds contexts to this list with * Dynamic List Interface functions. * - * SOURCE - */ + ***/ typedef struct SilcDListStruct { + SilcStack stack; SilcList list; void *current; void *prev; } *SilcDList; -/***/ /* SilcDListEntry structure, one entry in the list. This MUST NOT be used directly by the application. */ @@ -78,7 +90,8 @@ typedef struct SilcDListEntryStruct { * * DESCRIPTION * - * Initializes SilcDList. + * Initializes SilcDList. Returns the SilcDList context or NULL if system + * is out of memory. * ***/ @@ -90,6 +103,40 @@ SilcDList silc_dlist_init(void) list = (SilcDList)silc_malloc(sizeof(*list)); if (!list) return NULL; + list->stack = list->current = list->prev = NULL; + silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev); + + return list; +} + +/****f* silcutil/SilcDListAPI/silc_dlist_sinit + * + * SYNOPSIS + * + * static inline + * SilcDList silc_dlist_sinit(SilcStack stack); + * + * DESCRIPTION + * + * Initializes SilcDList. Returns the SilcDList context or NULL on error. + * This is same as silc_dlist_init but allocates the memory from `stack' + * if `stack' is non-NULL. + * + ***/ + +static inline +SilcDList silc_dlist_sinit(SilcStack stack) +{ + SilcDList list; + + if (stack) + stack = silc_stack_alloc(0, stack); + list = (SilcDList)silc_smalloc(stack, sizeof(*list)); + if (!list) { + silc_stack_free(stack); + return NULL; + } + list->stack = stack; list->current = list->prev = NULL; silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev); @@ -106,7 +153,9 @@ SilcDList silc_dlist_init(void) * DESCRIPTION * * Uninits and frees all memory. Must be called to free memory. Does NOT - * free the contexts saved by caller. + * free the contexts saved by caller. If the silc_dlist_sinit was used + * with SilcStack this will release all memory allocated by the SilcDList + * back to the SilcStack. * ***/ @@ -115,12 +164,14 @@ void silc_dlist_uninit(SilcDList list) { if (list) { SilcDListEntry e; + SilcStack stack = list->stack; silc_list_start(list->list); while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) { silc_list_del(list->list, e); - silc_free(e); + silc_sfree(stack, e); } - silc_free(list); + silc_sfree(stack, list); + silc_stack_free(stack); } } @@ -202,8 +253,8 @@ void silc_dlist_end(SilcDList list) static inline SilcBool silc_dlist_add(SilcDList list, void *context) { - SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e)); - if (!e) + SilcDListEntry e = (SilcDListEntry)silc_smalloc(list->stack, sizeof(*e)); + if (silc_unlikely(!e)) return FALSE; e->context = context; silc_list_add(list->list, e); @@ -228,8 +279,8 @@ SilcBool silc_dlist_add(SilcDList list, void *context) static inline SilcBool silc_dlist_insert(SilcDList list, void *context) { - SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e)); - if (!e) + SilcDListEntry e = (SilcDListEntry)silc_smalloc(list->stack, sizeof(*e)); + if (silc_unlikely(!e)) return FALSE; e->context = context; silc_list_insert(list->list, list->prev, e); @@ -241,22 +292,22 @@ SilcBool silc_dlist_insert(SilcDList list, void *context) * SYNOPSIS * * static inline - * void silc_dlist_del(SilcDList list, void *context); + * void silc_dlist_del(SilcDList list, void *entry); * * DESCRIPTION * - * Remove entry from the list. Returns < 0 on error, 0 otherwise. + * Remove entry from the list. * ***/ static inline -void silc_dlist_del(SilcDList list, void *context) +void silc_dlist_del(SilcDList list, void *entry) { SilcDListEntry e; silc_list_start(list->list); while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) { - if (e->context == context) { + if (e->context == entry) { silc_list_del(list->list, e); #if defined(SILC_DEBUG) memset(e, 'F', sizeof(*e)); @@ -265,7 +316,7 @@ void silc_dlist_del(SilcDList list, void *context) list->current = NULL; if (list->prev == e) list->prev = NULL; - silc_free(e); + silc_sfree(list->stack, e); break; } }