1 /* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk>
3 * Modified 2009 by Barret Rhoden <brho@cs.berkeley.edu>
5 * - No longer frees keys or values. It's up to the client to do that.
6 * - Uses the slab allocator for hash entry allocation.
7 * - Merges the iterator code with the main hash table code, mostly to avoid
8 * externing the hentry cache. */
10 #include <ros/common.h>
11 #include <hashtable.h>
19 Credit for primes table: Aaron Krowne
20 http://br.endernet.org/~akrowne/
21 http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
23 static const unsigned int primes[] = {
25 769, 1543, 3079, 6151,
26 12289, 24593, 49157, 98317,
27 196613, 393241, 786433, 1572869,
28 3145739, 6291469, 12582917, 25165843,
29 50331653, 100663319, 201326611, 402653189,
32 const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
33 #define APPLY_MAX_LOAD_FACTOR(size) \
35 //const float max_load_factor = 0.65;
37 struct kmem_cache *hentry_cache;
39 /* Call this once on bootup, after initializing the slab allocator. */
40 void hashtable_init(void)
42 hentry_cache = kmem_cache_create("hash_entry",
43 sizeof(struct hash_entry),
44 __alignof__(struct hash_entry), 0,
48 /* Common hash/equals functions. Don't call these directly. */
49 size_t __generic_hash(void *k)
51 /* 0x9e370001UL used by Linux (32 bit)
52 * (prime approx to the golden ratio to the max integer, IAW Knuth)
54 return (size_t)k * 0x9e370001UL;
57 ssize_t __generic_eq(void *k1, void *k2)
62 /*****************************************************************************/
64 create_hashtable(size_t minsize,
65 size_t (*hashf) (void*),
66 ssize_t (*eqf) (void*,void*))
69 size_t pindex, size = primes[0];
70 /* Check requested hashtable isn't too large */
71 if (minsize > (1u << 30)) return NULL;
72 /* Enforce size as prime */
73 for (pindex=0; pindex < prime_table_length; pindex++) {
74 if (primes[pindex] > minsize) { size = primes[pindex]; break; }
76 h = (hashtable_t *)kmalloc(sizeof(hashtable_t), 0);
77 if (NULL == h) return NULL; /*oom*/
78 h->table = (hash_entry_t **)kmalloc(sizeof(hash_entry_t*) * size, 0);
79 if (NULL == h->table) { kfree(h); return NULL; } /*oom*/
80 memset(h->table, 0, size * sizeof(hash_entry_t *));
81 h->tablelength = size;
82 h->primeindex = pindex;
86 h->loadlimit = APPLY_MAX_LOAD_FACTOR(size);
90 /*****************************************************************************/
92 hash(hashtable_t *h, void *k)
94 /* Aim to protect against poor hash functions by adding logic here
95 * - logic taken from java 1.4 hashtable source */
96 size_t i = h->hashfn(k);
98 i ^= ((i >> 14) | (i << 18)); /* >>> */
100 i ^= ((i >> 10) | (i << 22)); /* >>> */
104 /*****************************************************************************/
106 hashtable_expand(hashtable_t *h)
108 /* Double the size of the table to accomodate more entries */
109 hash_entry_t **newtable;
112 size_t newsize, i, index;
113 /* Check we're not hitting max capacity */
114 if (h->primeindex == (prime_table_length - 1)) return 0;
115 newsize = primes[++(h->primeindex)];
117 newtable = (hash_entry_t **)kmalloc(sizeof(hash_entry_t*) * newsize, 0);
118 if (NULL != newtable)
120 memset(newtable, 0, newsize * sizeof(hash_entry_t*));
121 /* This algorithm is not 'stable'. ie. it reverses the list
122 * when it transfers entries between the tables */
123 for (i = 0; i < h->tablelength; i++) {
124 while (NULL != (e = h->table[i])) {
125 h->table[i] = e->next;
126 index = indexFor(newsize,e->h);
127 e->next = newtable[index];
134 /* Plan B: realloc instead */
137 newtable = (hash_entry_t**)
138 krealloc(h->table, newsize*sizeof(hash_entry_t*), 0);
139 if (NULL == newtable) { (h->primeindex)--; return 0; }
141 memset(newtable[h->tablelength], 0, newsize - h->tablelength);
142 for (i = 0; i < h->tablelength; i++) {
143 for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
144 index = indexFor(newsize,e->h);
152 e->next = newtable[index];
158 h->tablelength = newsize;
159 h->loadlimit = APPLY_MAX_LOAD_FACTOR(newsize);
163 /*****************************************************************************/
165 hashtable_count(hashtable_t *h)
167 return h->entrycount;
170 /*****************************************************************************/
172 hashtable_insert(hashtable_t *h, void *k, void *v)
174 /* This method allows duplicate keys - but they shouldn't be used */
177 if (++(h->entrycount) > h->loadlimit)
179 /* Ignore the return value. If expand fails, we should
180 * still try cramming just this value into the existing table
181 * -- we may not have memory for a larger table, but one more
182 * element may be ok. Next time we insert, we'll try expanding again.*/
185 e = (hash_entry_t *)kmem_cache_alloc(hentry_cache, 0);
186 if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
188 index = indexFor(h->tablelength,e->h);
191 e->next = h->table[index];
196 /*****************************************************************************/
197 void * /* returns value associated with key */
198 hashtable_search(hashtable_t *h, void *k)
201 size_t hashvalue, index;
202 hashvalue = hash(h,k);
203 index = indexFor(h->tablelength,hashvalue);
207 /* Check hash value to short circuit heavier comparison */
208 if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
214 /*****************************************************************************/
215 void * /* returns value associated with key */
216 hashtable_remove(hashtable_t *h, void *k)
218 /* TODO: consider compacting the table when the load factor drops enough,
219 * or provide a 'compact' method. */
224 size_t hashvalue, index;
226 hashvalue = hash(h,k);
227 index = indexFor(h->tablelength,hash(h,k));
228 pE = &(h->table[index]);
232 /* Check hash value to short circuit heavier comparison */
233 if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
238 kmem_cache_free(hentry_cache, e);
247 /*****************************************************************************/
250 hashtable_destroy(hashtable_t *h)
252 if (hashtable_count(h))
253 warn("Destroying a non-empty hashtable, clean up after yourself!\n");
257 hash_entry_t **table = h->table;
258 for (i = 0; i < h->tablelength; i++) {
263 kmem_cache_free(hentry_cache, f);
270 /*****************************************************************************/
271 /* hashtable_iterator - iterator constructor, be sure to kfree this when
274 * If the htable isn't empty, e and index will refer to the first entry. */
277 hashtable_iterator(hashtable_t *h)
279 size_t i, tablelength;
280 hashtable_itr_t *itr = (hashtable_itr_t *)
281 kmalloc(sizeof(hashtable_itr_t), 0);
282 if (NULL == itr) return NULL;
286 tablelength = h->tablelength;
287 itr->index = tablelength;
288 if (0 == h->entrycount) return itr;
290 for (i = 0; i < tablelength; i++)
292 if (NULL != h->table[i])
294 itr->e = h->table[i];
302 /*****************************************************************************/
303 /* key - return the key of the (key,value) pair at the current position */
304 /* value - return the value of the (key,value) pair at the current position */
307 hashtable_iterator_key(hashtable_itr_t *i)
311 hashtable_iterator_value(hashtable_itr_t *i)
314 /*****************************************************************************/
315 /* advance - advance the iterator to the next element
316 * returns zero if advanced to end of table */
319 hashtable_iterator_advance(hashtable_itr_t *itr)
321 size_t j,tablelength;
322 hash_entry_t **table;
324 if (NULL == itr->e) return 0; /* stupidity check */
329 itr->parent = itr->e;
333 tablelength = itr->h->tablelength;
335 if (tablelength <= (j = ++(itr->index)))
340 table = itr->h->table;
341 while (NULL == (next = table[j]))
343 if (++j >= tablelength)
345 itr->index = tablelength;
355 /*****************************************************************************/
356 /* remove - remove the entry at the current iterator position
357 * and advance the iterator, if there is a successive
359 * If you want the value, read it before you remove:
360 * beware memory leaks if you don't.
361 * Returns zero if end of iteration. */
364 hashtable_iterator_remove(hashtable_itr_t *itr)
366 hash_entry_t *remember_e, *remember_parent;
370 if (NULL == (itr->parent))
372 /* element is head of a chain */
373 itr->h->table[itr->index] = itr->e->next;
375 /* element is mid-chain */
376 itr->parent->next = itr->e->next;
378 /* itr->e is now outside the hashtable */
380 itr->h->entrycount--;
382 /* Advance the iterator, correcting the parent */
383 remember_parent = itr->parent;
384 ret = hashtable_iterator_advance(itr);
385 if (itr->parent == remember_e) { itr->parent = remember_parent; }
386 kmem_cache_free(hentry_cache, remember_e);
390 /*****************************************************************************/
391 ssize_t /* returns zero if not found */
392 hashtable_iterator_search(hashtable_itr_t *itr,
393 hashtable_t *h, void *k)
395 hash_entry_t *e, *parent;
396 size_t hashvalue, index;
398 hashvalue = hash(h,k);
399 index = indexFor(h->tablelength,hashvalue);
405 /* Check hash value to short circuit heavier comparison */
406 if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
410 itr->parent = parent;
420 /* Runs func on each member of the hash table */
421 void hash_for_each(struct hashtable *hash, void func(void *, void *),
424 if (hashtable_count(hash)) {
425 struct hashtable_itr *iter = hashtable_iterator(hash);
427 void *item = hashtable_iterator_value(iter);
429 } while (hashtable_iterator_advance(iter));
434 /* Runs func on each member of the hash table, removing the item after
435 * processing it. Make sure func frees the item, o/w you'll leak. */
436 void hash_for_each_remove(struct hashtable *hash, void func(void *, void *),
439 if (hashtable_count(hash)) {
440 struct hashtable_itr *iter = hashtable_iterator(hash);
442 void *item = hashtable_iterator_value(iter);
444 } while (hashtable_iterator_remove(iter));
450 * Copyright (c) 2002, 2004, Christopher Clark
451 * All rights reserved.
453 * Redistribution and use in source and binary forms, with or without
454 * modification, are permitted provided that the following conditions
457 * * Redistributions of source code must retain the above copyright
458 * notice, this list of conditions and the following disclaimer.
460 * * Redistributions in binary form must reproduce the above copyright
461 * notice, this list of conditions and the following disclaimer in the
462 * documentation and/or other materials provided with the distribution.
464 * * Neither the name of the original author; nor the names of any contributors
465 * may be used to endorse or promote products derived from this software
466 * without specific prior written permission.
469 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
470 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
471 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
472 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
473 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
474 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
475 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
476 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
477 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
478 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
479 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.