1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * General purpose hash table implementation.
32 * Just uses the util_hash for now, but it might be better switch to a linear
33 * probing hash table implementation at some point -- as it is said they have
34 * better lookup and cache performance and it appears to be possible to write
35 * a lock-free implementation of such hash tables .
37 * @author José Fonseca <jfonseca@vmware.com>
45 #include "util_hash_table.h"
46 #include "util_hash.h"
51 struct util_hash_table
53 struct util_hash *head;
56 unsigned (*make_hash)(void *key);
58 /** Compare two keys */
59 int (*compare)(void *key1, void *key2);
62 struct util_hash_table_item
69 static struct util_hash_table_item *
70 util_hash_table_item(struct util_hash_iter iter)
72 return (struct util_hash_table_item *)util_hash_iter_data(iter);
75 drm_private struct util_hash_table *
76 util_hash_table_create(unsigned (*hash)(void *key),
77 int (*compare)(void *key1, void *key2))
79 struct util_hash_table *ht;
81 ht = malloc(sizeof(struct util_hash_table));
85 ht->head = util_hash_create();
92 ht->compare = compare;
97 static struct util_hash_iter
98 util_hash_table_find_iter(struct util_hash_table *ht,
99 void *key, unsigned key_hash)
101 struct util_hash_iter iter;
102 struct util_hash_table_item *item;
104 iter = util_hash_find(ht->head, key_hash);
105 while (!util_hash_iter_is_null(iter)) {
106 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
107 if (!ht->compare(item->key, key))
109 iter = util_hash_iter_next(iter);
115 static struct util_hash_table_item *
116 util_hash_table_find_item(struct util_hash_table *ht,
117 void *key, unsigned key_hash)
119 struct util_hash_iter iter;
120 struct util_hash_table_item *item;
122 iter = util_hash_find(ht->head, key_hash);
123 while (!util_hash_iter_is_null(iter)) {
124 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
125 if (!ht->compare(item->key, key))
127 iter = util_hash_iter_next(iter);
134 util_hash_table_set(struct util_hash_table *ht, void *key, void *value)
137 struct util_hash_table_item *item;
138 struct util_hash_iter iter;
144 key_hash = ht->make_hash(key);
146 item = util_hash_table_find_item(ht, key, key_hash);
148 /* TODO: key/value destruction? */
153 item = malloc(sizeof(struct util_hash_table_item));
160 iter = util_hash_insert(ht->head, key_hash, item);
161 if(util_hash_iter_is_null(iter)) {
167 drm_private void *util_hash_table_get(struct util_hash_table *ht, void *key)
170 struct util_hash_table_item *item;
176 key_hash = ht->make_hash(key);
178 item = util_hash_table_find_item(ht, key, key_hash);
185 drm_private void util_hash_table_remove(struct util_hash_table *ht, void *key)
188 struct util_hash_iter iter;
189 struct util_hash_table_item *item;
195 key_hash = ht->make_hash(key);
197 iter = util_hash_table_find_iter(ht, key, key_hash);
198 if(util_hash_iter_is_null(iter))
201 item = util_hash_table_item(iter);
205 util_hash_erase(ht->head, iter);
208 drm_private void util_hash_table_clear(struct util_hash_table *ht)
210 struct util_hash_iter iter;
211 struct util_hash_table_item *item;
217 iter = util_hash_first_node(ht->head);
218 while (!util_hash_iter_is_null(iter)) {
219 item = (struct util_hash_table_item *)util_hash_take(ht->head, util_hash_iter_key(iter));
221 iter = util_hash_first_node(ht->head);
225 drm_private void util_hash_table_foreach(struct util_hash_table *ht,
226 void (*callback)(void *key, void *value, void *data),
229 struct util_hash_iter iter;
230 struct util_hash_table_item *item;
236 iter = util_hash_first_node(ht->head);
237 while (!util_hash_iter_is_null(iter)) {
238 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
239 callback(item->key, item->value, data);
240 iter = util_hash_iter_next(iter);
244 drm_private void util_hash_table_destroy(struct util_hash_table *ht)
246 struct util_hash_iter iter;
247 struct util_hash_table_item *item;
253 iter = util_hash_first_node(ht->head);
254 while (!util_hash_iter_is_null(iter)) {
255 item = (struct util_hash_table_item *)util_hash_iter_data(iter);
257 iter = util_hash_iter_next(iter);
260 util_hash_delete(ht->head);