From: Pekka Riikonen Date: Tue, 3 Jul 2007 19:43:38 +0000 (+0000) Subject: Added SilcStack support for memory allocation. X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=e8504852258db5a63e542246b64c23f8b8624006;p=silc.git Added SilcStack support for memory allocation. --- diff --git a/lib/silcutil/silcdlist.h b/lib/silcutil/silcdlist.h index 87dfb4cc..54c2a8ba 100644 --- a/lib/silcutil/silcdlist.h +++ b/lib/silcutil/silcdlist.h @@ -52,6 +52,7 @@ * ***/ typedef struct SilcDListStruct { + SilcStack stack; SilcList list; void *current; void *prev; @@ -74,7 +75,7 @@ typedef struct SilcDListEntryStruct { * * DESCRIPTION * - * Initializes SilcDList. + * Initializes SilcDList. Returns the SilcDList context or NULL on error. * ***/ @@ -92,6 +93,40 @@ SilcDList silc_dlist_init(void) 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); + + return list; +} + /****f* silcutil/SilcDListAPI/silc_dlist_uninit * * SYNOPSIS @@ -102,7 +137,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. * ***/ @@ -111,12 +148,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); } } @@ -198,7 +237,7 @@ void silc_dlist_end(SilcDList list) static inline SilcBool silc_dlist_add(SilcDList list, void *context) { - SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e)); + SilcDListEntry e = (SilcDListEntry)silc_smalloc(list->stack, sizeof(*e)); if (silc_unlikely(!e)) return FALSE; e->context = context; @@ -224,7 +263,7 @@ 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)); + SilcDListEntry e = (SilcDListEntry)silc_smalloc(list->stack, sizeof(*e)); if (silc_unlikely(!e)) return FALSE; e->context = context; @@ -261,7 +300,7 @@ void silc_dlist_del(SilcDList list, void *entry) list->current = NULL; if (list->prev == e) list->prev = NULL; - silc_free(e); + silc_sfree(list->stack, e); break; } } diff --git a/lib/silcutil/silchashtable.c b/lib/silcutil/silchashtable.c index 6ba2e0a2..dd59263f 100644 --- a/lib/silcutil/silchashtable.c +++ b/lib/silcutil/silchashtable.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2006 Pekka Riikonen + Copyright (C) 2001 - 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 @@ -63,6 +63,7 @@ typedef struct SilcHashTableEntryStruct { /* Hash table. */ struct SilcHashTableStruct { + SilcStack stack; SilcHashTableEntry *table; SilcUInt32 table_size; SilcUInt32 entry_count; @@ -281,7 +282,7 @@ silc_hash_table_add_internal(SilcHashTable ht, void *key, void *context, SILC_HT_DEBUG(("Collision; adding new key to list")); - e->next = silc_calloc(1, sizeof(*e->next)); + e->next = silc_scalloc(ht->stack, 1, sizeof(*e->next)); if (!e->next) return FALSE; e->next->key = key; @@ -290,7 +291,7 @@ silc_hash_table_add_internal(SilcHashTable ht, void *key, void *context, } else { /* New key */ SILC_HT_DEBUG(("New key")); - *entry = silc_calloc(1, sizeof(**entry)); + *entry = silc_scalloc(ht->stack, 1, sizeof(**entry)); if (!(*entry)) return FALSE; (*entry)->key = key; @@ -325,7 +326,7 @@ silc_hash_table_replace_internal(SilcHashTable ht, void *key, void *context, ht->destructor_user_context); } else { /* New key */ - *entry = silc_calloc(1, sizeof(**entry)); + *entry = silc_scalloc(ht->stack, 1, sizeof(**entry)); if (!(*entry)) return FALSE; ht->entry_count++; @@ -348,7 +349,8 @@ silc_hash_table_replace_internal(SilcHashTable ht, void *key, void *context, destructor function, respectively. The `hash' is mandatory, the others are optional. */ -SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, +SilcHashTable silc_hash_table_alloc(SilcStack stack, + SilcUInt32 table_size, SilcHashFunction hash, void *hash_user_context, SilcHashCompare compare, @@ -363,17 +365,25 @@ SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, if (!hash) return NULL; - ht = silc_calloc(1, sizeof(*ht)); - if (!ht) + if (stack) + stack = silc_stack_alloc(0, stack); + + ht = silc_scalloc(stack, 1, sizeof(*ht)); + if (!ht) { + silc_stack_free(stack); return NULL; - ht->table = silc_calloc(table_size ? silc_hash_table_primesize(table_size, - &size_index) : - primesize[SILC_HASH_TABLE_SIZE], - sizeof(*ht->table)); + } + ht->table = silc_scalloc(stack, + table_size ? silc_hash_table_primesize(table_size, + &size_index) : + primesize[SILC_HASH_TABLE_SIZE], + sizeof(*ht->table)); if (!ht->table) { - silc_free(ht); + silc_stack_free(stack); + silc_sfree(stack, ht); return NULL; } + ht->stack = stack; ht->table_size = size_index; ht->hash = hash; ht->compare = compare; @@ -391,6 +401,7 @@ SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, void silc_hash_table_free(SilcHashTable ht) { + SilcStack stack = ht->stack; SilcHashTableEntry e, tmp; int i; @@ -401,12 +412,13 @@ void silc_hash_table_free(SilcHashTable ht) ht->destructor(e->key, e->context, ht->destructor_user_context); tmp = e; e = e->next; - silc_free(tmp); + silc_sfree(stack, tmp); } } - silc_free(ht->table); - silc_free(ht); + silc_sfree(stack, ht->table); + silc_sfree(stack, ht); + silc_stack_free(stack); } /* Returns the size of the hash table */ @@ -451,7 +463,7 @@ SilcBool silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context, the `context. The destructor function will be called for the replaced key and context. */ -SilcBool silc_hash_table_replace(SilcHashTable ht, void *key, void *context) +SilcBool silc_hash_table_set(SilcHashTable ht, void *key, void *context) { return silc_hash_table_replace_internal(ht, key, context, ht->hash, ht->hash_user_context); @@ -459,10 +471,10 @@ SilcBool silc_hash_table_replace(SilcHashTable ht, void *key, void *context) /* Same as above but with specific hash function. */ -SilcBool silc_hash_table_replace_ext(SilcHashTable ht, void *key, - void *context, - SilcHashFunction hash, - void *hash_user_context) +SilcBool silc_hash_table_set_ext(SilcHashTable ht, void *key, + void *context, + SilcHashFunction hash, + void *hash_user_context) { return silc_hash_table_replace_internal(ht, key, context, hash, hash_user_context); @@ -495,7 +507,7 @@ SilcBool silc_hash_table_del(SilcHashTable ht, void *key) if (ht->destructor) ht->destructor(e->key, e->context, ht->destructor_user_context); - silc_free(e); + silc_sfree(ht->stack, e); ht->entry_count--; @@ -545,7 +557,7 @@ SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key, if (ht->destructor) ht->destructor(e->key, e->context, ht->destructor_user_context); } - silc_free(e); + silc_sfree(ht->stack, e); ht->entry_count--; @@ -586,7 +598,7 @@ SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key, if (ht->destructor) ht->destructor(e->key, e->context, ht->destructor_user_context); - silc_free(e); + silc_sfree(ht->stack, e); ht->entry_count--; @@ -639,7 +651,7 @@ SilcBool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key, if (ht->destructor) ht->destructor(e->key, e->context, ht->destructor_user_context); } - silc_free(e); + silc_sfree(ht->stack, e); ht->entry_count--; @@ -827,7 +839,8 @@ void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size) ht->auto_rehash = FALSE; /* Allocate new table */ - ht->table = silc_calloc(primesize[size_index], sizeof(*ht->table)); + ht->table = silc_scalloc(ht->stack, + primesize[size_index], sizeof(*ht->table)); if (!ht->table) return; ht->table_size = size_index; @@ -842,14 +855,14 @@ void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size) e = e->next; /* Remove old entry */ - silc_free(tmp); + silc_sfree(ht->stack, tmp); } } ht->auto_rehash = auto_rehash; /* Remove old table */ - silc_free(table); + silc_sfree(ht->stack, table); } /* Same as above but with specific hash function. */ @@ -882,7 +895,8 @@ void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size, ht->auto_rehash = FALSE; /* Allocate new table */ - ht->table = silc_calloc(primesize[size_index], sizeof(*ht->table)); + ht->table = silc_scalloc(ht->stack, + primesize[size_index], sizeof(*ht->table)); if (!ht->table) return; ht->table_size = size_index; @@ -898,14 +912,14 @@ void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size, e = e->next; /* Remove old entry */ - silc_free(tmp); + silc_sfree(ht->stack, tmp); } } ht->auto_rehash = auto_rehash; /* Remove old table */ - silc_free(table); + silc_sfree(ht->stack, table); } /* Prepares the `htl' list structure sent as argument to be used in the diff --git a/lib/silcutil/silchashtable.h b/lib/silcutil/silchashtable.h index f7d21cb4..6cecb274 100644 --- a/lib/silcutil/silchashtable.h +++ b/lib/silcutil/silchashtable.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2006 Pekka Riikonen + Copyright (C) 2001 - 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 @@ -24,14 +24,15 @@ * Implementation of collision resistant hash table. This is a hash table * that provides a reliable (what you add there stays there, and duplicate * keys are allowed) with as fast reference to the key as possible. If - * there are a lot of duplicate keys in the hash table the lookup gets - * slower of course. However, this is reliable and no data is lost at any - * point. If you know that you never have duplicate keys then this is as - * fast as any simple hash table. + * there are a lot of duplicate keys in the hash table the lookup slows down. + * However, this is reliable and no data is lost at any point. If you know + * that you never have duplicate keys then this is as fast as any simple hash + * table. * * The interface provides many ways to search the hash table including * an extended interface where caller can specify its own hash and comparison - * functions. + * functions. The interface also supports SilcStack and all memory allocated + * by the hash table can be allocated from SilcStack. * * There are two ways to traverse the entire hash table if this feature * is needed. There exists a foreach function that calls a foreach @@ -39,8 +40,8 @@ * SilcHashTableList structure and traverse the hash table inside while() * using the list structure. Both are equally fast. * - * The hash table is not thread safe. If same hash table context is used in - * multi thread environment concurrency control must be employed. + * The hash table is not thread safe. If same SilcHashtable context is used + * in multi thread environment concurrency control must be employed. * ***/ @@ -172,7 +173,8 @@ typedef void (*SilcHashForeach)(void *key, void *context, void *user_context); * * SYNOPSIS * - * SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, + * SilcHashTable silc_hash_table_alloc(SilcStack stack, + * SilcUInt32 table_size, * SilcHashFunction hash, * void *hash_user_context, * SilcHashCompare compare, @@ -183,7 +185,8 @@ typedef void (*SilcHashForeach)(void *key, void *context, void *user_context); * * DESCRIPTION * - * Allocates new hash table and returns it. If the `table_size' is not + * Allocates new hash table and returns it. If the `stack' is non-NULL + * the hash table is allocated from `stack'. If the `table_size' is not * zero then the hash table size is the size provided. If zero then the * default size will be used. Note that if the `table_size' is provided * it should be a prime. The `hash', `compare' and `destructor' are @@ -192,7 +195,8 @@ typedef void (*SilcHashForeach)(void *key, void *context, void *user_context); * are optional. * ***/ -SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, +SilcHashTable silc_hash_table_alloc(SilcStack stack, + SilcUInt32 table_size, SilcHashFunction hash, void *hash_user_context, SilcHashCompare compare, @@ -212,6 +216,10 @@ SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, * Frees the hash table. The destructor function provided in the * silc_hash_table_alloc will be called for all keys in the hash table. * + * If the SilcStack was given to silc_hash_table_alloc this call will + * release all memory allocated during the life time of the `ht' back + * to the SilcStack. + * ***/ void silc_hash_table_free(SilcHashTable ht); @@ -260,12 +268,12 @@ SilcUInt32 silc_hash_table_count(SilcHashTable ht); ***/ SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context); -/****f* silcutil/SilcHashTableAPI/silc_hash_table_replace +/****f* silcutil/SilcHashTableAPI/silc_hash_table_set * * SYNOPSIS * - * SilcBool silc_hash_table_replace(SilcHashTable ht, void *key, - * void *context); + * SilcBool silc_hash_table_set(SilcHashTable ht, void *key, + * void *context); * * DESCRIPTION * @@ -275,7 +283,7 @@ SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context); * replaced key and context. * ***/ -SilcBool silc_hash_table_replace(SilcHashTable ht, void *key, void *context); +SilcBool silc_hash_table_set(SilcHashTable ht, void *key, void *context); /****f* silcutil/SilcHashTableAPI/silc_hash_table_del * @@ -505,14 +513,14 @@ SilcBool silc_hash_table_add_ext(SilcHashTable ht, SilcHashFunction hash, void *hash_user_context); -/****f* silcutil/SilcHashTableAPI/silc_hash_table_replace_ext +/****f* silcutil/SilcHashTableAPI/silc_hash_table_set_ext * * SYNOPSIS * - * SilcBool silc_hash_table_replace_ext(SilcHashTable ht, void *key, - * void *context, - * SilcHashFunction hash, - * void *hash_user_context); + * SilcBool silc_hash_table_set_ext(SilcHashTable ht, void *key, + * void *context, + * SilcHashFunction hash, + * void *hash_user_context); * * DESCRIPTION * @@ -525,10 +533,10 @@ SilcBool silc_hash_table_add_ext(SilcHashTable ht, * function. If not provided the hash table's default is used. * ***/ -SilcBool silc_hash_table_replace_ext(SilcHashTable ht, - void *key, void *context, - SilcHashFunction hash, - void *hash_user_context); +SilcBool silc_hash_table_set_ext(SilcHashTable ht, + void *key, void *context, + SilcHashFunction hash, + void *hash_user_context); /****f* silcutil/SilcHashTableAPI/silc_hash_table_del_ext * diff --git a/lib/silcutil/tests/test_silchashtable.c b/lib/silcutil/tests/test_silchashtable.c index 622fc453..a09727b3 100644 --- a/lib/silcutil/tests/test_silchashtable.c +++ b/lib/silcutil/tests/test_silchashtable.c @@ -120,7 +120,7 @@ SilcBool alloc_table() SILC_LOG_DEBUG(("Allocating hash table with %d entries (%s)", count, auto_rehash ? "auto rehash" : "no auto rehash")); - t = silc_hash_table_alloc(0, hash_entry, NULL, + t = silc_hash_table_alloc(NULL, 0, hash_entry, NULL, hash_compare, NULL, hash_destructor, NULL, auto_rehash);