Changeset 0ca7286 in mainline for uspace/lib
- Timestamp:
- 2012-07-21T11:19:27Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2732c94
- Parents:
- 1c1da4b
- Location:
- uspace/lib
- Files:
-
- 7 edited
-
block/libblock.c (modified) (5 diffs)
-
c/generic/adt/hash_table.c (modified) (7 diffs)
-
c/generic/async.c (modified) (10 diffs)
-
c/include/adt/hash_table.h (modified) (3 diffs)
-
c/include/adt/list.h (modified) (1 diff)
-
nic/include/nic_wol_virtues.h (modified) (1 diff)
-
nic/src/nic_wol_virtues.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/block/libblock.c
r1c1da4b r0ca7286 62 62 static LIST_INITIALIZE(dcl); 63 63 64 #define CACHE_BUCKETS_LOG2 1065 #define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)66 64 67 65 typedef struct { … … 256 254 } 257 255 258 static hash_index_t cache_hash(unsigned long *key) 259 { 260 return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1); 261 } 262 263 static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item) 256 static size_t cache_key_hash(unsigned long *key) 257 { 258 /* As recommended by Effective Java, 2nd Edition. */ 259 size_t hash = 17; 260 hash = 31 * hash + key[1]; 261 hash = 31 * hash + key[0]; 262 return hash; 263 } 264 265 static size_t cache_hash(const link_t *item) 266 { 267 block_t *b = hash_table_get_instance(item, block_t, hash_link); 268 unsigned long key[] = { 269 LOWER32(b->lba), 270 UPPER32(b->lba) 271 }; 272 273 return cache_key_hash(key); 274 } 275 276 static bool cache_match(unsigned long *key, size_t keys, const link_t *item) 264 277 { 265 278 block_t *b = hash_table_get_instance(item, block_t, hash_link); … … 267 280 } 268 281 269 static void cache_remove_callback(link_t *item) 270 { 271 } 272 273 static hash_table_operations_t cache_ops = { 282 283 static hash_table_ops_t cache_ops = { 274 284 .hash = cache_hash, 275 .compare = cache_compare, 276 .remove_callback = cache_remove_callback 285 .key_hash = cache_key_hash, 286 .match = cache_match, 287 .equal = 0, 288 .remove_callback = 0 277 289 }; 278 290 … … 305 317 cache->blocks_cluster = cache->lblock_size / devcon->pblock_size; 306 318 307 if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2, 308 &cache_ops)) { 319 if (!hash_table_create(&cache->block_hash, 0, 2, &cache_ops)) { 309 320 free(cache); 310 321 return ENOMEM; … … 540 551 b->lba = ba; 541 552 b->pba = ba_ltop(devcon, b->lba); 542 hash_table_insert(&cache->block_hash, key,&b->hash_link);553 hash_table_insert(&cache->block_hash, &b->hash_link); 543 554 544 555 /* -
uspace/lib/c/generic/adt/hash_table.c
r1c1da4b r0ca7286 34 34 35 35 /* 36 * This is an implementation of generic chained hash table. 36 * This is an implementation of a generic resizable chained hash table. 37 * 38 * The table grows to 2*n+1 buckets each time, starting at n == 89, 39 * per Thomas Wang's recommendation: 40 * http://www.concentric.net/~Ttwang/tech/hashsize.htm 41 * 42 * This policy produces prime table sizes for the first five resizes 43 * and generally produces table sizes which are either prime or 44 * have fairly large (prime/odd) divisors. Having a prime table size 45 * mitigates the use of suboptimal hash functions and distributes 46 * items over the whole table. 37 47 */ 38 48 … … 44 54 #include <str.h> 45 55 56 /* Optimal initial bucket count. See comment above. */ 57 #define HT_MIN_BUCKETS 89 58 /* The table is resized when the average load per bucket exceeds this number. */ 59 #define HT_MAX_LOAD 2 60 61 62 static size_t round_up_size(size_t size); 63 static bool alloc_table(size_t bucket_cnt, list_t **pbuckets); 64 static void item_inserted(hash_table_t *h); 65 static void item_removed(hash_table_t *h); 66 static inline void remove_item(hash_table_t *h, link_t *item); 67 static size_t remove_duplicates(hash_table_t *h, unsigned long key[]); 68 static size_t remove_matching(hash_table_t *h, unsigned long key[], size_t key_cnt); 69 70 /* Dummy do nothing callback to invoke in place of remove_callback == NULL. */ 71 static void nop_remove_callback(link_t *item) 72 { 73 /* no-op */ 74 } 75 76 46 77 /** Create chained hash table. 47 78 * 48 79 * @param h Hash table structure. Will be initialized by this call. 49 * @param m Number of hash table buckets. 80 * @param init_size Initial desired number of hash table buckets. Pass zero 81 * if you want the default initial size. 50 82 * @param max_keys Maximal number of keys needed to identify an item. 51 * @param op Hash table operations structure. 83 * @param op Hash table operations structure. remove_callback() 84 * is optional and can be NULL if no action is to be taken 85 * upon removal. equal() is optional if and only if 86 * hash_table_insert_unique() will never be invoked. 87 * All other operations are mandatory. 52 88 * 53 89 * @return True on success 54 90 * 55 91 */ 56 bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,57 hash_table_op erations_t *op)92 bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_keys, 93 hash_table_ops_t *op) 58 94 { 59 95 assert(h); 60 assert(op && op->hash && op-> compare);96 assert(op && op->hash && op->key_hash && op->match); 61 97 assert(max_keys > 0); 62 98 63 h->entry = malloc(m * sizeof(list_t)); 64 if (!h->entry) 99 h->bucket_cnt = round_up_size(init_size); 100 101 if (!alloc_table(h->bucket_cnt, &h->bucket)) 65 102 return false; 66 103 67 memset((void *) h->entry, 0, m * sizeof(list_t));68 69 hash_count_t i;70 for (i = 0; i < m; i++)71 list_initialize(&h->entry[i]);72 73 h->entries = m;74 104 h->max_keys = max_keys; 105 h->items = 0; 75 106 h->op = op; 76 107 108 if (h->op->remove_callback == 0) 109 h->op->remove_callback = nop_remove_callback; 110 77 111 return true; 78 112 } … … 84 118 void hash_table_clear(hash_table_t *h) 85 119 { 86 for (hash_count_t chain = 0; chain < h->entries; ++chain) { 87 link_t *cur; 88 link_t *next; 89 90 for (cur = h->entry[chain].head.next; 91 cur != &h->entry[chain].head; 92 cur = next) { 93 next = cur->next; 120 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 121 list_foreach_safe(h->bucket[idx], cur, next) { 94 122 list_remove(cur); 95 123 h->op->remove_callback(cur); 96 124 } 97 125 } 126 127 h->items = 0; 128 129 /* Shrink the table to its minimum size if possible. */ 130 if (HT_MIN_BUCKETS < h->bucket_cnt) { 131 list_t *new_buckets; 132 if (alloc_table(HT_MIN_BUCKETS, &new_buckets)) { 133 free(h->bucket); 134 h->bucket = new_buckets; 135 h->bucket_cnt = HT_MIN_BUCKETS; 136 } 137 } 98 138 } 99 139 … … 106 146 { 107 147 assert(h); 108 assert(h->entry); 109 110 free(h->entry); 148 assert(h->bucket); 149 150 free(h->bucket); 151 152 h->bucket = 0; 153 h->bucket_cnt = 0; 111 154 } 112 155 … … 117 160 * @param item Item to be inserted into the hash table. 118 161 */ 119 void hash_table_insert(hash_table_t *h, unsigned long key[],link_t *item)162 void hash_table_insert(hash_table_t *h, link_t *item) 120 163 { 121 164 assert(item); 122 assert(h && h->op && h->op->hash && h->op->compare); 123 124 hash_index_t chain = h->op->hash(key); 125 assert(chain < h->entries); 126 127 list_append(item, &h->entry[chain]); 165 assert(h && h->bucket); 166 assert(h->op && h->op->hash); 167 168 size_t idx = h->op->hash(item) % h->bucket_cnt; 169 170 assert(idx < h->bucket_cnt); 171 172 list_append(item, &h->bucket[idx]); 173 item_inserted(h); 174 } 175 176 177 /** Insert item into a hash table if not already present. 178 * 179 * @param h Hash table. 180 * @param key Array of all keys necessary to compute hash index. 181 * @param item Item to be inserted into the hash table. 182 * 183 * @return False if such an item had already been inserted. 184 * @return True if the inserted item was the only item with such a lookup key. 185 */ 186 bool hash_table_insert_unique(hash_table_t *h, link_t *item) 187 { 188 assert(item); 189 assert(h && h->bucket && h->bucket_cnt); 190 assert(h->op && h->op->hash && h->op->equal); 191 192 size_t item_hash = h->op->hash(item); 193 size_t idx = item_hash % h->bucket_cnt; 194 195 assert(idx < h->bucket_cnt); 196 197 /* Check for duplicates. */ 198 list_foreach(h->bucket[idx], cur) { 199 /* 200 * We could filter out items using their hashes first, but 201 * calling equal() might very well be just as fast. 202 */ 203 if (h->op->equal(cur, item)) 204 return false; 205 } 206 207 list_append(item, &h->bucket[idx]); 208 item_inserted(h); 209 210 return true; 128 211 } 129 212 … … 138 221 link_t *hash_table_find(hash_table_t *h, unsigned long key[]) 139 222 { 140 assert(h && h->op && h->op->hash && h->op->compare); 141 142 hash_index_t chain = h->op->hash(key); 143 assert(chain < h->entries); 144 145 list_foreach(h->entry[chain], cur) { 146 if (h->op->compare(key, h->max_keys, cur)) { 147 /* 148 * The entry is there. 223 assert(h && h->bucket); 224 assert(h->op && h->op->key_hash && h->op->match); 225 226 size_t key_hash = h->op->key_hash(key); 227 size_t idx = key_hash % h->bucket_cnt; 228 229 assert(idx < h->bucket_cnt); 230 231 list_foreach(h->bucket[idx], cur) { 232 /* 233 * Is this is the item we are looking for? We could have first 234 * checked if the hashes match but op->match() may very well be 235 * just as fast as op->hash(). 236 */ 237 if (h->op->match(key, h->max_keys, cur)) { 238 return cur; 239 } 240 } 241 242 return NULL; 243 } 244 245 246 /** Apply function to all items in hash table. 247 * 248 * @param h Hash table. 249 * @param f Function to be applied. Return false if no more items 250 * should be visited. The functor must not delete the successor 251 * of the item passed in the first argument. 252 * @param arg Argument to be passed to the function. 253 * 254 */ 255 void hash_table_apply(hash_table_t *h, bool (*f)(link_t *, void *), void *arg) 256 { 257 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 258 list_foreach_safe(h->bucket[idx], cur, next) { 259 /* 260 * The next pointer had already been saved. f() may safely 261 * delete cur (but not next!). 149 262 */ 150 return cur; 151 } 152 } 153 154 return NULL; 263 if (!f(cur, arg)) 264 return; 265 } 266 } 155 267 } 156 268 … … 163 275 * the hash table. 164 276 * @param keys Number of keys in the 'key' array. 165 * 166 */ 167 void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys) 168 { 169 assert(h && h->op && h->op->hash && h->op->compare && 277 * 278 * @return Returns the number of removed items. 279 */ 280 size_t hash_table_remove(hash_table_t *h, unsigned long key[], size_t key_cnt) 281 { 282 assert(h && h->bucket); 283 assert(h && h->op && h->op->hash && 170 284 h->op->remove_callback); 171 assert(keys <= h->max_keys); 172 173 if (keys == h->max_keys) { 285 assert(key_cnt <= h->max_keys); 286 287 /* All keys are known, remove from a specific bucket. */ 288 if (key_cnt == h->max_keys) { 289 return remove_duplicates(h, key); 290 } else { 174 291 /* 175 * All keys are known, hash_table_find() can be used to find the 176 * entry. 177 */ 178 179 link_t *cur = hash_table_find(h, key); 180 if (cur) { 181 list_remove(cur); 182 h->op->remove_callback(cur); 183 } 184 185 return; 186 } 187 292 * Fewer keys were passed. 293 * Any partially matching entries are to be removed. 294 */ 295 return remove_matching(h, key, key_cnt); 296 } 297 } 298 299 /** Removes an item already present in the table. The item must be in the table.*/ 300 void hash_table_remove_item(hash_table_t *h, link_t *item) 301 { 302 assert(item); 303 assert(h && h->bucket); 304 305 remove_item(h, item); 306 } 307 308 /** Unlink the item from a bucket, update statistics and resize if needed. */ 309 static inline void remove_item(hash_table_t *h, link_t *item) 310 { 311 assert(item); 312 313 list_remove(item); 314 item_removed(h); 315 h->op->remove_callback(item); 316 } 317 318 /** Removes all items matching key in the bucket key hashes to. */ 319 static size_t remove_duplicates(hash_table_t *h, unsigned long key[]) 320 { 321 assert(h && h->bucket); 322 assert(h->op && h->op->key_hash && h->op->match); 323 324 size_t key_hash = h->op->key_hash(key); 325 size_t idx = key_hash % h->bucket_cnt; 326 327 assert(idx < h->bucket_cnt); 328 329 size_t removed = 0; 330 331 list_foreach_safe(h->bucket[idx], cur, next) { 332 if (h->op->match(key, h->max_keys, cur)) { 333 ++removed; 334 remove_item(h, cur); 335 } 336 } 337 338 return removed; 339 } 340 341 /** Removes all items in any bucket in the table that match the partial key. */ 342 static size_t remove_matching(hash_table_t *h, unsigned long key[], 343 size_t key_cnt) 344 { 345 assert(h && h->bucket); 346 assert(key_cnt < h->max_keys); 347 348 size_t removed = 0; 188 349 /* 189 350 * Fewer keys were passed. 190 351 * Any partially matching entries are to be removed. 191 352 */ 192 hash_index_t chain; 193 for (chain = 0; chain < h->entries; chain++) { 194 for (link_t *cur = h->entry[chain].head.next; 195 cur != &h->entry[chain].head; 196 cur = cur->next) { 197 if (h->op->compare(key, keys, cur)) { 198 link_t *hlp; 199 200 hlp = cur; 201 cur = cur->prev; 202 203 list_remove(hlp); 204 h->op->remove_callback(hlp); 205 206 continue; 353 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 354 list_foreach_safe(h->bucket[idx], cur, next) { 355 if (h->op->match(key, key_cnt, cur)) { 356 ++removed; 357 remove_item(h, cur); 207 358 } 208 359 } 209 360 } 210 } 211 212 /** Apply function to all items in hash table. 213 * 214 * @param h Hash table. 215 * @param f Function to be applied. 216 * @param arg Argument to be passed to the function. 217 * 218 */ 219 void hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg) 220 { 221 for (hash_index_t bucket = 0; bucket < h->entries; bucket++) { 222 link_t *cur; 223 link_t *next; 224 225 for (cur = h->entry[bucket].head.next; cur != &h->entry[bucket].head; 226 cur = next) { 227 /* 228 * The next pointer must be stored prior to the functor 229 * call to allow using destructor as the functor (the 230 * free function could overwrite the cur->next pointer). 231 */ 232 next = cur->next; 233 f(cur, arg); 234 } 235 } 236 } 361 362 return removed; 363 364 } 365 366 /** Rounds up size to the nearest suitable table size. */ 367 static size_t round_up_size(size_t size) 368 { 369 size_t rounded_size = HT_MIN_BUCKETS; 370 371 while (rounded_size < size) { 372 rounded_size = 2 * rounded_size + 1; 373 } 374 375 return rounded_size; 376 } 377 378 /** Allocates and initializes the desired number of buckets. True if successful.*/ 379 static bool alloc_table(size_t bucket_cnt, list_t **pbuckets) 380 { 381 assert(pbuckets && HT_MIN_BUCKETS <= bucket_cnt); 382 383 list_t *buckets = malloc(bucket_cnt * sizeof(list_t)); 384 if (!buckets) 385 return false; 386 387 for (size_t i = 0; i < bucket_cnt; i++) 388 list_initialize(&buckets[i]); 389 390 *pbuckets = buckets; 391 return true; 392 } 393 394 /** Allocates and rehashes items to a new table. Frees the old table. */ 395 static void resize(hash_table_t *h, size_t new_bucket_cnt) 396 { 397 assert(h && h->bucket); 398 399 list_t *new_buckets; 400 401 /* Leave the table as is if we cannot resize. */ 402 if (!alloc_table(new_bucket_cnt, &new_buckets)) 403 return; 404 405 /* Rehash all the items to the new table. */ 406 for (size_t old_idx = 0; old_idx < h->bucket_cnt; ++old_idx) { 407 list_foreach_safe(h->bucket[old_idx], cur, next) { 408 size_t new_idx = h->op->hash(cur) % new_bucket_cnt; 409 list_remove(cur); 410 list_append(cur, &new_buckets[new_idx]); 411 } 412 } 413 414 free(h->bucket); 415 h->bucket = new_buckets; 416 h->bucket_cnt = new_bucket_cnt; 417 } 418 419 /** Shrinks the table if needed. */ 420 static void item_removed(hash_table_t *h) 421 { 422 --h->items; 423 424 if (HT_MIN_BUCKETS < h->items && h->items <= HT_MAX_LOAD * h->bucket_cnt / 4) { 425 /* 426 * Keep the bucket_cnt odd (possibly also prime). 427 * Shrink from 2n + 1 to n. Integer division discards the +1. 428 */ 429 size_t new_bucket_cnt = h->bucket_cnt / 2; 430 resize(h, new_bucket_cnt); 431 } 432 } 433 434 /** Grows the table if needed. */ 435 static void item_inserted(hash_table_t *h) 436 { 437 ++h->items; 438 439 /* Grow the table if the average bucket load exceeds the maximum. */ 440 if (HT_MAX_LOAD * h->bucket_cnt < h->items) { 441 /* Keep the bucket_cnt odd (possibly also prime). */ 442 size_t new_bucket_cnt = 2 * h->bucket_cnt + 1; 443 resize(h, new_bucket_cnt); 444 } 445 } 446 237 447 238 448 /** @} -
uspace/lib/c/generic/async.c
r1c1da4b r0ca7286 115 115 #include <macros.h> 116 116 117 #define CLIENT_HASH_TABLE_BUCKETS 32118 #define CONN_HASH_TABLE_BUCKETS 32119 117 120 118 /** Session data */ … … 392 390 static LIST_INITIALIZE(timeout_list); 393 391 394 static hash_index_t client_hash(unsigned long key[])392 static size_t client_key_hash(unsigned long key[]) 395 393 { 396 394 assert(key); 397 398 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 399 } 400 401 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 395 /* LOWER32(in_task_id) */ 396 return key[0] >> 4; 397 } 398 399 static size_t client_hash(const link_t *item) 400 { 401 client_t *client = hash_table_get_instance(item, client_t, link); 402 403 unsigned long key[2] = { 404 LOWER32(client->in_task_id), 405 UPPER32(client->in_task_id), 406 }; 407 408 return client_key_hash(key); 409 } 410 411 static bool client_match(unsigned long key[], size_t keys, const link_t *item) 402 412 { 403 413 assert(key); … … 410 420 } 411 421 412 static void client_remove(link_t *item)413 {414 }415 422 416 423 /** Operations for the client hash table. */ 417 static hash_table_op erations_t client_hash_table_ops = {424 static hash_table_ops_t client_hash_table_ops = { 418 425 .hash = client_hash, 419 .compare = client_compare, 420 .remove_callback = client_remove 426 .key_hash = client_key_hash, 427 .match = client_match, 428 .equal = 0, 429 .remove_callback = 0 421 430 }; 422 431 … … 428 437 * 429 438 */ 430 static hash_index_t conn_hash(unsigned long key[])439 static size_t conn_key_hash(unsigned long key[]) 431 440 { 432 441 assert(key); 433 434 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 442 return key[0] >> 4; 443 } 444 445 static size_t conn_hash(const link_t *item) 446 { 447 connection_t *conn = hash_table_get_instance(item, connection_t, link); 448 unsigned long key = conn->in_phone_hash; 449 return conn_key_hash(&key); 435 450 } 436 451 … … 444 459 * 445 460 */ 446 static int conn_compare(unsigned long key[], hash_count_t keys,link_t *item)461 static bool conn_match(unsigned long key[], size_t keys, const link_t *item) 447 462 { 448 463 assert(key); … … 453 468 } 454 469 470 static bool conn_equal(const link_t *item1, const link_t *item2) 471 { 472 connection_t *c1 = hash_table_get_instance(item1, connection_t, link); 473 connection_t *c2 = hash_table_get_instance(item2, connection_t, link); 474 475 return c1->in_phone_hash == c2->in_phone_hash; 476 } 477 455 478 static void conn_remove(link_t *item) 456 479 { … … 458 481 459 482 /** Operations for the connection hash table. */ 460 static hash_table_op erations_t conn_hash_table_ops = {483 static hash_table_ops_t conn_hash_table_ops = { 461 484 .hash = conn_hash, 462 .compare = conn_compare, 485 .key_hash = conn_key_hash, 486 .match = conn_match, 487 .equal = conn_equal, 463 488 .remove_callback = conn_remove 464 489 }; … … 715 740 716 741 atomic_set(&client->refcnt, 1); 717 hash_table_insert(&client_hash_table, key,&client->link);742 hash_table_insert(&client_hash_table, &client->link); 718 743 } 719 744 } … … 915 940 916 941 /* Add connection to the connection hash table */ 917 unsigned long key = conn->in_phone_hash;918 942 919 943 futex_down(&async_futex); 920 hash_table_insert(&conn_hash_table, & key, &conn->link);944 hash_table_insert(&conn_hash_table, &conn->link); 921 945 futex_up(&async_futex); 922 946 … … 1110 1134 void __async_init(void) 1111 1135 { 1112 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1113 2, &client_hash_table_ops)) 1136 if (!hash_table_create(&client_hash_table, 0, 2, &client_hash_table_ops)) 1114 1137 abort(); 1115 1138 1116 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1117 1, &conn_hash_table_ops)) 1139 if (!hash_table_create(&conn_hash_table, 0, 1, &conn_hash_table_ops)) 1118 1140 abort(); 1119 1141 -
uspace/lib/c/include/adt/hash_table.h
r1c1da4b r0ca7286 40 40 #include <bool.h> 41 41 42 typedef unsigned long hash_count_t;43 typedef unsigned long hash_index_t;44 42 45 43 /** Set of operations for hash table. */ 46 44 typedef struct { 47 /** Hash function. 48 * 49 * @param key Array of keys needed to compute hash index. 50 * All keys must be passed. 51 * 52 * @return Index into hash table. 53 * 45 /** Returns the hash of the key stored in the item. 54 46 */ 55 hash_index_t (*hash)(unsigned long key[]);47 size_t (*hash)(const link_t *item); 56 48 57 /** Hash table item comparison function. 49 /** Returns the hash of the key. 50 */ 51 size_t (*key_hash)(unsigned long key[]); 52 53 /** Hash table item match function. 58 54 * 59 55 * @param key Array of keys that will be compared with item. It is … … 63 59 * 64 60 */ 65 int (*compare)(unsigned long key[], hash_count_t keys, link_t *item); 61 bool (*match)(unsigned long key[], size_t keys, const link_t *item); 62 63 /** 64 */ 65 bool (*equal)(const link_t *item1, const link_t *item2); 66 66 67 67 /** Hash table item removal callback. 68 * 69 * Must not invoke any mutating functions of the hash table. 68 70 * 69 71 * @param item Item that was removed from the hash table. 70 *71 72 */ 72 73 void (*remove_callback)(link_t *item); 73 } hash_table_op erations_t;74 } hash_table_ops_t; 74 75 75 76 /** Hash table structure. */ 76 77 typedef struct { 77 list_t *entry; 78 hash_count_t entries; 79 hash_count_t max_keys; 80 hash_table_operations_t *op; 78 list_t *bucket; 79 size_t bucket_cnt; 80 size_t max_keys; 81 size_t items; 82 hash_table_ops_t *op; 81 83 } hash_table_t; 82 84 … … 84 86 list_get_instance((item), type, member) 85 87 86 extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,87 hash_table_operations_t *);88 extern bool hash_table_create(hash_table_t *, size_t, size_t, 89 hash_table_ops_t *); 88 90 extern void hash_table_clear(hash_table_t *); 89 extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *); 91 extern void hash_table_insert(hash_table_t *, link_t *); 92 extern bool hash_table_insert_unique(hash_table_t *, link_t *); 90 93 extern link_t *hash_table_find(hash_table_t *, unsigned long []); 91 extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t); 94 extern size_t hash_table_remove(hash_table_t *, unsigned long [], size_t); 95 extern void hash_table_remove_item(hash_table_t *, link_t *); 92 96 extern void hash_table_destroy(hash_table_t *); 93 extern void hash_table_apply(hash_table_t *, void (*)(link_t *, void *),94 void *);97 extern void hash_table_apply(hash_table_t *, bool (*)(link_t *, void *), 98 void *); 95 99 96 100 #endif -
uspace/lib/c/include/adt/list.h
r1c1da4b r0ca7286 71 71 iterator != &(list).head; iterator = iterator->next) 72 72 73 /** Unlike list_foreach(), allows removing items while traversing a list. 74 * 75 * @code 76 * list_t mylist; 77 * typedef struct item { 78 * int value; 79 * link_t item_link; 80 * } item_t; 81 * 82 * //.. 83 * 84 * // Print each list element's value and remove the element from the list. 85 * list_foreach_safe(mylist, cur_link, next_link) { 86 * item_t *cur_item = list_get_instance(cur_link, item_t, item_link); 87 * printf("%d\n", cur_item->value); 88 * list_remove(cur_link); 89 * } 90 * @endcode 91 * 92 * @param list List to traverse. 93 * @param iterator Iterator to the current element of the list. 94 * The item this iterator points may be safely removed 95 * from the list. 96 * @param next_iter Iterator to the next element of the list. 97 */ 98 #define list_foreach_safe(list, iterator, next_iter) \ 99 for (link_t *iterator = (list).head.next, \ 100 *next_iter = iterator->next; \ 101 iterator != &(list).head; \ 102 iterator = next_iter, next_iter = iterator->next) 103 104 73 105 #define assert_link_not_used(link) \ 74 106 assert(((link)->prev == NULL) && ((link)->next == NULL)) -
uspace/lib/nic/include/nic_wol_virtues.h
r1c1da4b r0ca7286 51 51 * Operations for table 52 52 */ 53 hash_table_op erations_t table_operations;53 hash_table_ops_t table_operations; 54 54 /** 55 55 * WOL virtues hashed by their ID's. -
uspace/lib/nic/src/nic_wol_virtues.c
r1c1da4b r0ca7286 40 40 #include <errno.h> 41 41 42 #define NIC_WV_HASH_COUNT 32 43 44 /** 45 * Hash table helper function 46 */ 47 static int nic_wv_compare(unsigned long key[], hash_count_t keys, 48 link_t *item) 42 43 /* 44 * Hash table helper functions 45 */ 46 47 static size_t nic_wv_key_hash(unsigned long keys[]) 48 { 49 return keys[0]; 50 } 51 52 static size_t nic_wv_hash(const link_t *item) 53 { 54 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item; 55 unsigned long key = virtue->id; 56 return nic_wv_key_hash(&key); 57 } 58 59 static bool nic_wv_match(unsigned long key[], size_t keys, const link_t *item) 49 60 { 50 61 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item; … … 53 64 54 65 /** 55 * Hash table helper function56 */57 static void nic_wv_rc(link_t *item)58 {59 }60 61 /**62 * Hash table helper function63 */64 static hash_index_t nic_wv_hash(unsigned long keys[])65 {66 return keys[0] % NIC_WV_HASH_COUNT;67 }68 69 /**70 66 * Initializes the WOL virtues structure 71 67 * … … 77 73 int nic_wol_virtues_init(nic_wol_virtues_t *wvs) 78 74 { 79 bzero(wvs, sizeof (nic_wol_virtues_t)); 80 wvs->table_operations.compare = nic_wv_compare; 75 bzero(wvs, sizeof(nic_wol_virtues_t)); 81 76 wvs->table_operations.hash = nic_wv_hash; 82 wvs->table_operations.remove_callback = nic_wv_rc; 83 if (!hash_table_create(&wvs->table, NIC_WV_HASH_COUNT, 1, 84 &wvs->table_operations)) { 77 wvs->table_operations.key_hash = nic_wv_key_hash; 78 wvs->table_operations.match = nic_wv_match; 79 wvs->table_operations.equal = 0; 80 wvs->table_operations.remove_callback = 0; 81 82 if (!hash_table_create(&wvs->table, 0, 1, &wvs->table_operations)) { 85 83 return ENOMEM; 86 84 } … … 172 170 } while (NULL != 173 171 hash_table_find(&wvs->table, (unsigned long *) &virtue->id)); 174 hash_table_insert(&wvs->table, 175 (unsigned long *) &virtue->id, &virtue->item); 172 hash_table_insert(&wvs->table, &virtue->item); 176 173 virtue->next = wvs->lists[virtue->type]; 177 174 wvs->lists[virtue->type] = virtue;
Note:
See TracChangeset
for help on using the changeset viewer.
