2 * Copyright (c) 1984 through 2008, William LeFebvre
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
16 * * Neither the name of William LeFebvre nor the names of other
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 /* The file hash.c is generated from hash.m4c via the preprocessor M4 */
38 * Hash table functions: init, add, lookup, first, next, sizeinfo.
39 * This is a conventional "bucket hash". The key is hashed in to a number
40 * less than or equal to the number of buckets and the result is used
41 * to index in to the array of buckets. Each bucket is a linked list
42 * that contains all the key/value pairs which hashed to that index.
66 if ((i
/j
)==floor(i
/j
))
83 string_hash(hash_table
*ht
, char *key
)
90 while ((ch
= (unsigned char)*key
++) != '\0')
99 s
= s
+ (ch
<< shifting
);
104 return (s
% ht
->num_buckets
);
107 static void ll_init(llist
*q
)
114 static llistitem
*ll_newitem(int size
)
119 qi
= emalloc(sizeof(llistitem
) + size
);
120 qi
->datum
= ((char *)qi
+ sizeof(llistitem
));
124 static void ll_freeitem(llistitem
*li
)
130 static void ll_add(llist
*q
, llistitem
*new)
138 static void ll_extract(llist
*q
, llistitem
*qi
, llistitem
*last
)
147 last
->next
= qi
->next
;
153 #define LL_FIRST(q) ((q)->head)
154 #define LL_NEXT(q, qi) ((qi) != NULL ? (qi)->next : NULL)
155 #define LL_ISEMPTY(ll) ((ll)->count == 0)
166 ll_next(llist
*q
, llistitem
*qi
)
169 return (qi
!= NULL
? qi
->next
: NULL
);
173 ll_isempty(llist
*ll
)
176 return (ll
->count
== 0);
181 * hash_table *hash_create(int num)
183 * Creates a hash table structure with at least "num" buckets.
195 /* create the resultant structure */
196 result
= emalloc(sizeof(hash_table
));
198 /* adjust bucket count to be prime */
199 num
= next_prime(num
);
201 /* create the buckets */
202 bytes
= sizeof(bucket_t
) * num
;
203 result
->buckets
= b
= emalloc(bytes
);
204 result
->num_buckets
= num
;
206 /* create each bucket as a linked list */
218 * unsigned int hash_count(hash_table *ht)
220 * Return total number of elements contained in hash table.
225 hash_count(hash_table
*ht
)
229 register int cnt
= 0;
230 register bucket_t
*bucket
;
232 bucket
= ht
->buckets
;
233 while (i
++ < ht
->num_buckets
)
235 cnt
+= bucket
->list
.count
;
244 * void hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht)
246 * Fill in "sizes" with information about bucket lengths in hash
251 hash_sizeinfo(unsigned int *sizes
, int max
, hash_table
*ht
)
256 register bucket_t
*bucket
;
258 memzero(sizes
, max
* sizeof(unsigned int));
260 bucket
= ht
->buckets
;
262 while (i
++ < ht
->num_buckets
)
264 idx
= bucket
->list
.count
;
265 sizes
[idx
>= max
? max
-1 : idx
]++;
277 * void hash_add_uint(hash_table *ht, unsigned int key, void *value)
279 * Add an element to table "ht". The element is described by
280 * "key" and "value". Return NULL on success. If the key
281 * already exists in the table, then no action is taken and
282 * the data for the existing element is returned.
283 * Key type is unsigned int
287 hash_add_uint(hash_table
*ht
, unsigned int key
, void *value
)
298 /* allocate the space we will need */
299 newli
= ll_newitem(sizeof(hash_item_uint
));
300 hi
= (hash_item_uint
*)newli
->datum
;
302 /* fill in the values */
306 /* hash to the bucket */
307 bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)]);
309 /* walk the list to make sure we do not have a duplicate */
310 ll
= &(bucket
->list
);
314 h
= (hash_item_uint
*)li
->datum
;
321 li
= LL_NEXT(ll
, li
);
325 /* is there already one there? */
328 /* add the unique element to the buckets list */
329 ll_add(&(bucket
->list
), newli
);
334 /* free the stuff we just allocated */
336 return ((hash_item_uint
*)(li
->datum
))->value
;
341 * void *hash_replace_uint(hash_table *ht, unsigned int key, void *value)
343 * Replace an existing value in the hash table with a new one and
344 * return the old value. If the key does not already exist in
345 * the hash table, add a new element and return NULL.
346 * Key type is unsigned int
350 hash_replace_uint(hash_table
*ht
, unsigned int key
, void *value
)
360 /* find the bucket */
361 bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)]);
363 /* walk the list until we find the existing item */
364 ll
= &(bucket
->list
);
368 hi
= (hash_item_uint
*)li
->datum
;
372 /* found it: now replace the value with the new one */
377 li
= LL_NEXT(ll
, li
);
380 /* if the element wasnt found, add it */
383 li
= ll_newitem(sizeof(hash_item_uint
));
384 hi
= (hash_item_uint
*)li
->datum
;
387 ll_add(&(bucket
->list
), li
);
390 /* return the old value (so it can be freed) */
395 * void *hash_lookup_uint(hash_table *ht, unsigned int key)
397 * Look up "key" in "ht" and return the associated value. If "key"
398 * is not found, return NULL. Key type is unsigned int
402 hash_lookup_uint(hash_table
*ht
, unsigned int key
)
413 if ((bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)])) != NULL
)
415 ll
= &(bucket
->list
);
419 h
= (hash_item_uint
*)li
->datum
;
426 li
= LL_NEXT(ll
, li
);
433 * void *hash_remove_uint(hash_table *ht, unsigned int key)
435 * Remove the element associated with "key" from the hash table
436 * "ht". Return the value or NULL if the key was not found.
440 hash_remove_uint(hash_table
*ht
, unsigned int key
)
452 if ((bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)])) != NULL
)
454 ll
= &(bucket
->list
);
459 hi
= (hash_item_uint
*)li
->datum
;
463 ll_extract(ll
, li
, lilast
);
471 li
= LL_NEXT(ll
, li
);
478 * hash_item_uint *hash_first_uint(hash_table *ht, hash_pos *pos)
480 * First function to call when iterating through all items in the hash
481 * table. Returns the first item in "ht" and initializes "*pos" to track
482 * the current position.
486 hash_first_uint(hash_table
*ht
, hash_pos
*pos
)
489 /* initialize pos for first item in first bucket */
490 pos
->num_buckets
= ht
->num_buckets
;
491 pos
->hash_bucket
= ht
->buckets
;
495 /* find the first non-empty bucket */
496 while(pos
->hash_bucket
->list
.count
== 0)
499 if (++pos
->curr
>= pos
->num_buckets
)
505 /* set and return the first item */
506 pos
->ll_item
= LL_FIRST(&(pos
->hash_bucket
->list
));
507 return (hash_item_uint
*)pos
->ll_item
->datum
;
512 * hash_item_uint *hash_next_uint(hash_pos *pos)
514 * Return the next item in the hash table, using "pos" as a description
515 * of the present position in the hash table. "pos" also identifies the
516 * specific hash table. Return NULL if there are no more elements.
520 hash_next_uint(hash_pos
*pos
)
525 /* move item to last and check for NULL */
526 if ((pos
->ll_last
= pos
->ll_item
) == NULL
)
528 /* are we really at the end of the hash table? */
529 if (pos
->curr
>= pos
->num_buckets
)
531 /* yes: return NULL */
534 /* no: regrab first item in current bucket list (might be NULL) */
535 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
539 /* get the next item in the llist */
540 li
= LL_NEXT(&(pos
->hash_bucket
->list
), pos
->ll_item
);
543 /* if its NULL we have to find another bucket */
546 /* locate another bucket */
549 /* move to the next one */
551 if (++pos
->curr
>= pos
->num_buckets
)
553 /* at the end of the hash table */
558 /* get the first element (might be NULL) */
559 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
562 /* li is the next element to dish out */
564 return (hash_item_uint
*)li
->datum
;
568 * void *hash_remove_pos_uint(hash_pos *pos)
570 * Remove the hash table entry pointed to by position marker "pos".
571 * The data from the entry is returned upon success, otherwise NULL.
576 hash_remove_pos_uint(hash_pos
*pos
)
584 if (pos
== NULL
|| pos
->ll_last
== pos
->ll_item
)
589 /* at this point pos contains the item to remove (ll_item)
590 and its predecesor (ll_last) */
591 /* extract the item from the llist */
593 ll_extract(&(pos
->hash_bucket
->list
), li
, pos
->ll_last
);
595 /* retain the data */
596 hi
= (hash_item_uint
*)li
->datum
;
601 /* back up to previous item */
602 /* its okay for ll_item to be null: hash_next will detect it */
603 pos
->ll_item
= pos
->ll_last
;
611 * void hash_add_pid(hash_table *ht, pid_t key, void *value)
613 * Add an element to table "ht". The element is described by
614 * "key" and "value". Return NULL on success. If the key
615 * already exists in the table, then no action is taken and
616 * the data for the existing element is returned.
621 hash_add_pid(hash_table
*ht
, pid_t key
, void *value
)
632 /* allocate the space we will need */
633 newli
= ll_newitem(sizeof(hash_item_pid
));
634 hi
= (hash_item_pid
*)newli
->datum
;
636 /* fill in the values */
640 /* hash to the bucket */
641 bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)]);
643 /* walk the list to make sure we do not have a duplicate */
644 ll
= &(bucket
->list
);
648 h
= (hash_item_pid
*)li
->datum
;
655 li
= LL_NEXT(ll
, li
);
659 /* is there already one there? */
662 /* add the unique element to the buckets list */
663 ll_add(&(bucket
->list
), newli
);
668 /* free the stuff we just allocated */
670 return ((hash_item_pid
*)(li
->datum
))->value
;
675 * void *hash_replace_pid(hash_table *ht, pid_t key, void *value)
677 * Replace an existing value in the hash table with a new one and
678 * return the old value. If the key does not already exist in
679 * the hash table, add a new element and return NULL.
684 hash_replace_pid(hash_table
*ht
, pid_t key
, void *value
)
694 /* find the bucket */
695 bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)]);
697 /* walk the list until we find the existing item */
698 ll
= &(bucket
->list
);
702 hi
= (hash_item_pid
*)li
->datum
;
706 /* found it: now replace the value with the new one */
711 li
= LL_NEXT(ll
, li
);
714 /* if the element wasnt found, add it */
717 li
= ll_newitem(sizeof(hash_item_pid
));
718 hi
= (hash_item_pid
*)li
->datum
;
721 ll_add(&(bucket
->list
), li
);
724 /* return the old value (so it can be freed) */
729 * void *hash_lookup_pid(hash_table *ht, pid_t key)
731 * Look up "key" in "ht" and return the associated value. If "key"
732 * is not found, return NULL. Key type is pid_t
736 hash_lookup_pid(hash_table
*ht
, pid_t key
)
747 if ((bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)])) != NULL
)
749 ll
= &(bucket
->list
);
753 h
= (hash_item_pid
*)li
->datum
;
760 li
= LL_NEXT(ll
, li
);
767 * void *hash_remove_pid(hash_table *ht, pid_t key)
769 * Remove the element associated with "key" from the hash table
770 * "ht". Return the value or NULL if the key was not found.
774 hash_remove_pid(hash_table
*ht
, pid_t key
)
786 if ((bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)])) != NULL
)
788 ll
= &(bucket
->list
);
793 hi
= (hash_item_pid
*)li
->datum
;
797 ll_extract(ll
, li
, lilast
);
805 li
= LL_NEXT(ll
, li
);
812 * hash_item_pid *hash_first_pid(hash_table *ht, hash_pos *pos)
814 * First function to call when iterating through all items in the hash
815 * table. Returns the first item in "ht" and initializes "*pos" to track
816 * the current position.
820 hash_first_pid(hash_table
*ht
, hash_pos
*pos
)
823 /* initialize pos for first item in first bucket */
824 pos
->num_buckets
= ht
->num_buckets
;
825 pos
->hash_bucket
= ht
->buckets
;
829 /* find the first non-empty bucket */
830 while(pos
->hash_bucket
->list
.count
== 0)
833 if (++pos
->curr
>= pos
->num_buckets
)
839 /* set and return the first item */
840 pos
->ll_item
= LL_FIRST(&(pos
->hash_bucket
->list
));
841 return (hash_item_pid
*)pos
->ll_item
->datum
;
846 * hash_item_pid *hash_next_pid(hash_pos *pos)
848 * Return the next item in the hash table, using "pos" as a description
849 * of the present position in the hash table. "pos" also identifies the
850 * specific hash table. Return NULL if there are no more elements.
854 hash_next_pid(hash_pos
*pos
)
859 /* move item to last and check for NULL */
860 if ((pos
->ll_last
= pos
->ll_item
) == NULL
)
862 /* are we really at the end of the hash table? */
863 if (pos
->curr
>= pos
->num_buckets
)
865 /* yes: return NULL */
868 /* no: regrab first item in current bucket list (might be NULL) */
869 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
873 /* get the next item in the llist */
874 li
= LL_NEXT(&(pos
->hash_bucket
->list
), pos
->ll_item
);
877 /* if its NULL we have to find another bucket */
880 /* locate another bucket */
883 /* move to the next one */
885 if (++pos
->curr
>= pos
->num_buckets
)
887 /* at the end of the hash table */
892 /* get the first element (might be NULL) */
893 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
896 /* li is the next element to dish out */
898 return (hash_item_pid
*)li
->datum
;
902 * void *hash_remove_pos_pid(hash_pos *pos)
904 * Remove the hash table entry pointed to by position marker "pos".
905 * The data from the entry is returned upon success, otherwise NULL.
910 hash_remove_pos_pid(hash_pos
*pos
)
918 if (pos
== NULL
|| pos
->ll_last
== pos
->ll_item
)
923 /* at this point pos contains the item to remove (ll_item)
924 and its predecesor (ll_last) */
925 /* extract the item from the llist */
927 ll_extract(&(pos
->hash_bucket
->list
), li
, pos
->ll_last
);
929 /* retain the data */
930 hi
= (hash_item_pid
*)li
->datum
;
933 /* free up the space */
936 /* back up to previous item */
937 /* its okay for ll_item to be null: hash_next will detect it */
938 pos
->ll_item
= pos
->ll_last
;
946 * void hash_add_string(hash_table *ht, char * key, void *value)
948 * Add an element to table "ht". The element is described by
949 * "key" and "value". Return NULL on success. If the key
950 * already exists in the table, then no action is taken and
951 * the data for the existing element is returned.
956 hash_add_string(hash_table
*ht
, char * key
, void *value
)
960 hash_item_string
*hi
;
967 /* allocate the space we will need */
968 newli
= ll_newitem(sizeof(hash_item_string
));
969 hi
= (hash_item_string
*)newli
->datum
;
971 /* fill in the values */
972 hi
->key
= estrdup(key
);
975 /* hash to the bucket */
976 bucket
= &(ht
->buckets
[string_hash(ht
, key
)]);
978 /* walk the list to make sure we do not have a duplicate */
979 ll
= &(bucket
->list
);
983 h
= (hash_item_string
*)li
->datum
;
985 if (strcmp(key
, k1
) == 0)
990 li
= LL_NEXT(ll
, li
);
994 /* is there already one there? */
997 /* add the unique element to the buckets list */
998 ll_add(&(bucket
->list
), newli
);
1003 /* free the stuff we just allocated */
1005 return ((hash_item_string
*)(li
->datum
))->value
;
1010 * void *hash_replace_string(hash_table *ht, char * key, void *value)
1012 * Replace an existing value in the hash table with a new one and
1013 * return the old value. If the key does not already exist in
1014 * the hash table, add a new element and return NULL.
1015 * Key type is char *
1019 hash_replace_string(hash_table
*ht
, char * key
, void *value
)
1023 hash_item_string
*hi
;
1026 void *result
= NULL
;
1029 /* find the bucket */
1030 bucket
= &(ht
->buckets
[string_hash(ht
, key
)]);
1032 /* walk the list until we find the existing item */
1033 ll
= &(bucket
->list
);
1037 hi
= (hash_item_string
*)li
->datum
;
1039 if (strcmp(key
, k1
) == 0)
1041 /* found it: now replace the value with the new one */
1046 li
= LL_NEXT(ll
, li
);
1049 /* if the element wasnt found, add it */
1052 li
= ll_newitem(sizeof(hash_item_string
));
1053 hi
= (hash_item_string
*)li
->datum
;
1054 hi
->key
= estrdup(key
);
1056 ll_add(&(bucket
->list
), li
);
1059 /* return the old value (so it can be freed) */
1064 * void *hash_lookup_string(hash_table *ht, char * key)
1066 * Look up "key" in "ht" and return the associated value. If "key"
1067 * is not found, return NULL. Key type is char *
1071 hash_lookup_string(hash_table
*ht
, char * key
)
1077 hash_item_string
*h
;
1082 if ((bucket
= &(ht
->buckets
[string_hash(ht
, key
)])) != NULL
)
1084 ll
= &(bucket
->list
);
1088 h
= (hash_item_string
*)li
->datum
;
1090 if (strcmp(key
, k1
) == 0)
1095 li
= LL_NEXT(ll
, li
);
1102 * void *hash_remove_string(hash_table *ht, char * key)
1104 * Remove the element associated with "key" from the hash table
1105 * "ht". Return the value or NULL if the key was not found.
1109 hash_remove_string(hash_table
*ht
, char * key
)
1116 hash_item_string
*hi
;
1121 if ((bucket
= &(ht
->buckets
[string_hash(ht
, key
)])) != NULL
)
1123 ll
= &(bucket
->list
);
1128 hi
= (hash_item_string
*)li
->datum
;
1130 if (strcmp(key
, k1
) == 0)
1132 ll_extract(ll
, li
, lilast
);
1140 li
= LL_NEXT(ll
, li
);
1147 * hash_item_string *hash_first_string(hash_table *ht, hash_pos *pos)
1149 * First function to call when iterating through all items in the hash
1150 * table. Returns the first item in "ht" and initializes "*pos" to track
1151 * the current position.
1155 hash_first_string(hash_table
*ht
, hash_pos
*pos
)
1158 /* initialize pos for first item in first bucket */
1159 pos
->num_buckets
= ht
->num_buckets
;
1160 pos
->hash_bucket
= ht
->buckets
;
1162 pos
->ll_last
= NULL
;
1164 /* find the first non-empty bucket */
1165 while(pos
->hash_bucket
->list
.count
== 0)
1168 if (++pos
->curr
>= pos
->num_buckets
)
1174 /* set and return the first item */
1175 pos
->ll_item
= LL_FIRST(&(pos
->hash_bucket
->list
));
1176 return (hash_item_string
*)pos
->ll_item
->datum
;
1181 * hash_item_string *hash_next_string(hash_pos *pos)
1183 * Return the next item in the hash table, using "pos" as a description
1184 * of the present position in the hash table. "pos" also identifies the
1185 * specific hash table. Return NULL if there are no more elements.
1189 hash_next_string(hash_pos
*pos
)
1194 /* move item to last and check for NULL */
1195 if ((pos
->ll_last
= pos
->ll_item
) == NULL
)
1197 /* are we really at the end of the hash table? */
1198 if (pos
->curr
>= pos
->num_buckets
)
1200 /* yes: return NULL */
1203 /* no: regrab first item in current bucket list (might be NULL) */
1204 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
1208 /* get the next item in the llist */
1209 li
= LL_NEXT(&(pos
->hash_bucket
->list
), pos
->ll_item
);
1212 /* if its NULL we have to find another bucket */
1215 /* locate another bucket */
1216 pos
->ll_last
= NULL
;
1218 /* move to the next one */
1220 if (++pos
->curr
>= pos
->num_buckets
)
1222 /* at the end of the hash table */
1223 pos
->ll_item
= NULL
;
1227 /* get the first element (might be NULL) */
1228 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
1231 /* li is the next element to dish out */
1233 return (hash_item_string
*)li
->datum
;
1237 * void *hash_remove_pos_string(hash_pos *pos)
1239 * Remove the hash table entry pointed to by position marker "pos".
1240 * The data from the entry is returned upon success, otherwise NULL.
1245 hash_remove_pos_string(hash_pos
*pos
)
1250 hash_item_string
*hi
;
1254 if (pos
== NULL
|| pos
->ll_last
== pos
->ll_item
)
1259 /* at this point pos contains the item to remove (ll_item)
1260 and its predecesor (ll_last) */
1261 /* extract the item from the llist */
1263 ll_extract(&(pos
->hash_bucket
->list
), li
, pos
->ll_last
);
1265 /* retain the data */
1266 hi
= (hash_item_string
*)li
->datum
;
1269 /* free up the space */
1274 /* back up to previous item */
1275 /* its okay for ll_item to be null: hash_next will detect it */
1276 pos
->ll_item
= pos
->ll_last
;
1284 * void hash_add_pidthr(hash_table *ht, pidthr_t key, void *value)
1286 * Add an element to table "ht". The element is described by
1287 * "key" and "value". Return NULL on success. If the key
1288 * already exists in the table, then no action is taken and
1289 * the data for the existing element is returned.
1290 * Key type is pidthr_t
1294 hash_add_pidthr(hash_table
*ht
, pidthr_t key
, void *value
)
1298 hash_item_pidthr
*hi
;
1299 hash_item_pidthr
*h
;
1305 /* allocate the space we will need */
1306 newli
= ll_newitem(sizeof(hash_item_pidthr
));
1307 hi
= (hash_item_pidthr
*)newli
->datum
;
1309 /* fill in the values */
1313 /* hash to the bucket */
1314 bucket
= &(ht
->buckets
[((key
.k_thr
* 10000 + key
.k_pid
) % ht
->num_buckets
)]);
1316 /* walk the list to make sure we do not have a duplicate */
1317 ll
= &(bucket
->list
);
1321 h
= (hash_item_pidthr
*)li
->datum
;
1323 if ((key
.k_pid
== k1
.k_pid
&& key
.k_thr
== k1
.k_thr
))
1328 li
= LL_NEXT(ll
, li
);
1332 /* is there already one there? */
1335 /* add the unique element to the buckets list */
1336 ll_add(&(bucket
->list
), newli
);
1341 /* free the stuff we just allocated */
1343 return ((hash_item_pidthr
*)(li
->datum
))->value
;
1348 * void *hash_replace_pidthr(hash_table *ht, pidthr_t key, void *value)
1350 * Replace an existing value in the hash table with a new one and
1351 * return the old value. If the key does not already exist in
1352 * the hash table, add a new element and return NULL.
1353 * Key type is pidthr_t
1357 hash_replace_pidthr(hash_table
*ht
, pidthr_t key
, void *value
)
1361 hash_item_pidthr
*hi
;
1364 void *result
= NULL
;
1367 /* find the bucket */
1368 bucket
= &(ht
->buckets
[((key
.k_thr
* 10000 + key
.k_pid
) % ht
->num_buckets
)]);
1370 /* walk the list until we find the existing item */
1371 ll
= &(bucket
->list
);
1375 hi
= (hash_item_pidthr
*)li
->datum
;
1377 if ((key
.k_pid
== k1
.k_pid
&& key
.k_thr
== k1
.k_thr
))
1379 /* found it: now replace the value with the new one */
1384 li
= LL_NEXT(ll
, li
);
1387 /* if the element wasnt found, add it */
1390 li
= ll_newitem(sizeof(hash_item_pidthr
));
1391 hi
= (hash_item_pidthr
*)li
->datum
;
1394 ll_add(&(bucket
->list
), li
);
1397 /* return the old value (so it can be freed) */
1402 * void *hash_lookup_pidthr(hash_table *ht, pidthr_t key)
1404 * Look up "key" in "ht" and return the associated value. If "key"
1405 * is not found, return NULL. Key type is pidthr_t
1409 hash_lookup_pidthr(hash_table
*ht
, pidthr_t key
)
1415 hash_item_pidthr
*h
;
1420 if ((bucket
= &(ht
->buckets
[((key
.k_thr
* 10000 + key
.k_pid
) % ht
->num_buckets
)])) != NULL
)
1422 ll
= &(bucket
->list
);
1426 h
= (hash_item_pidthr
*)li
->datum
;
1428 if ((key
.k_pid
== k1
.k_pid
&& key
.k_thr
== k1
.k_thr
))
1433 li
= LL_NEXT(ll
, li
);
1440 * void *hash_remove_pidthr(hash_table *ht, pidthr_t key)
1442 * Remove the element associated with "key" from the hash table
1443 * "ht". Return the value or NULL if the key was not found.
1447 hash_remove_pidthr(hash_table
*ht
, pidthr_t key
)
1454 hash_item_pidthr
*hi
;
1459 if ((bucket
= &(ht
->buckets
[((key
.k_thr
* 10000 + key
.k_pid
) % ht
->num_buckets
)])) != NULL
)
1461 ll
= &(bucket
->list
);
1466 hi
= (hash_item_pidthr
*)li
->datum
;
1468 if ((key
.k_pid
== k1
.k_pid
&& key
.k_thr
== k1
.k_thr
))
1470 ll_extract(ll
, li
, lilast
);
1478 li
= LL_NEXT(ll
, li
);
1485 * hash_item_pidthr *hash_first_pidthr(hash_table *ht, hash_pos *pos)
1487 * First function to call when iterating through all items in the hash
1488 * table. Returns the first item in "ht" and initializes "*pos" to track
1489 * the current position.
1493 hash_first_pidthr(hash_table
*ht
, hash_pos
*pos
)
1496 /* initialize pos for first item in first bucket */
1497 pos
->num_buckets
= ht
->num_buckets
;
1498 pos
->hash_bucket
= ht
->buckets
;
1500 pos
->ll_last
= NULL
;
1502 /* find the first non-empty bucket */
1503 while(pos
->hash_bucket
->list
.count
== 0)
1506 if (++pos
->curr
>= pos
->num_buckets
)
1512 /* set and return the first item */
1513 pos
->ll_item
= LL_FIRST(&(pos
->hash_bucket
->list
));
1514 return (hash_item_pidthr
*)pos
->ll_item
->datum
;
1519 * hash_item_pidthr *hash_next_pidthr(hash_pos *pos)
1521 * Return the next item in the hash table, using "pos" as a description
1522 * of the present position in the hash table. "pos" also identifies the
1523 * specific hash table. Return NULL if there are no more elements.
1527 hash_next_pidthr(hash_pos
*pos
)
1532 /* move item to last and check for NULL */
1533 if ((pos
->ll_last
= pos
->ll_item
) == NULL
)
1535 /* are we really at the end of the hash table? */
1536 if (pos
->curr
>= pos
->num_buckets
)
1538 /* yes: return NULL */
1541 /* no: regrab first item in current bucket list (might be NULL) */
1542 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
1546 /* get the next item in the llist */
1547 li
= LL_NEXT(&(pos
->hash_bucket
->list
), pos
->ll_item
);
1550 /* if its NULL we have to find another bucket */
1553 /* locate another bucket */
1554 pos
->ll_last
= NULL
;
1556 /* move to the next one */
1558 if (++pos
->curr
>= pos
->num_buckets
)
1560 /* at the end of the hash table */
1561 pos
->ll_item
= NULL
;
1565 /* get the first element (might be NULL) */
1566 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
1569 /* li is the next element to dish out */
1571 return (hash_item_pidthr
*)li
->datum
;
1575 * void *hash_remove_pos_pidthr(hash_pos *pos)
1577 * Remove the hash table entry pointed to by position marker "pos".
1578 * The data from the entry is returned upon success, otherwise NULL.
1583 hash_remove_pos_pidthr(hash_pos
*pos
)
1588 hash_item_pidthr
*hi
;
1591 if (pos
== NULL
|| pos
->ll_last
== pos
->ll_item
)
1596 /* at this point pos contains the item to remove (ll_item)
1597 and its predecesor (ll_last) */
1598 /* extract the item from the llist */
1600 ll_extract(&(pos
->hash_bucket
->list
), li
, pos
->ll_last
);
1602 /* retain the data */
1603 hi
= (hash_item_pidthr
*)li
->datum
;
1606 /* free up the space */
1609 /* back up to previous item */
1610 /* its okay for ll_item to be null: hash_next will detect it */
1611 pos
->ll_item
= pos
->ll_last
;
1620 * void hash_add_lwpid(hash_table *ht, lwpid_t key, void *value)
1622 * Add an element to table "ht". The element is described by
1623 * "key" and "value". Return NULL on success. If the key
1624 * already exists in the table, then no action is taken and
1625 * the data for the existing element is returned.
1626 * Key type is lwpid_t
1630 hash_add_lwpid(hash_table
*ht
, lwpid_t key
, void *value
)
1634 hash_item_lwpid
*hi
;
1641 /* allocate the space we will need */
1642 newli
= ll_newitem(sizeof(hash_item_lwpid
));
1643 hi
= (hash_item_lwpid
*)newli
->datum
;
1645 /* fill in the values */
1649 /* hash to the bucket */
1650 bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)]);
1652 /* walk the list to make sure we do not have a duplicate */
1653 ll
= &(bucket
->list
);
1657 h
= (hash_item_lwpid
*)li
->datum
;
1664 li
= LL_NEXT(ll
, li
);
1668 /* is there already one there? */
1671 /* add the unique element to the buckets list */
1672 ll_add(&(bucket
->list
), newli
);
1677 /* free the stuff we just allocated */
1679 return ((hash_item_lwpid
*)(li
->datum
))->value
;
1684 * void *hash_replace_lwpid(hash_table *ht, lwpid_t key, void *value)
1686 * Replace an existing value in the hash table with a new one and
1687 * return the old value. If the key does not already exist in
1688 * the hash table, add a new element and return NULL.
1689 * Key type is lwpid_t
1693 hash_replace_lwpid(hash_table
*ht
, lwpid_t key
, void *value
)
1697 hash_item_lwpid
*hi
;
1700 void *result
= NULL
;
1703 /* find the bucket */
1704 bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)]);
1706 /* walk the list until we find the existing item */
1707 ll
= &(bucket
->list
);
1711 hi
= (hash_item_lwpid
*)li
->datum
;
1715 /* found it: now replace the value with the new one */
1720 li
= LL_NEXT(ll
, li
);
1723 /* if the element wasnt found, add it */
1726 li
= ll_newitem(sizeof(hash_item_lwpid
));
1727 hi
= (hash_item_lwpid
*)li
->datum
;
1730 ll_add(&(bucket
->list
), li
);
1733 /* return the old value (so it can be freed) */
1738 * void *hash_lookup_lwpid(hash_table *ht, lwpid_t key)
1740 * Look up "key" in "ht" and return the associated value. If "key"
1741 * is not found, return NULL. Key type is lwpid_t
1745 hash_lookup_lwpid(hash_table
*ht
, lwpid_t key
)
1756 if ((bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)])) != NULL
)
1758 ll
= &(bucket
->list
);
1762 h
= (hash_item_lwpid
*)li
->datum
;
1769 li
= LL_NEXT(ll
, li
);
1776 * void *hash_remove_lwpid(hash_table *ht, lwpid_t key)
1778 * Remove the element associated with "key" from the hash table
1779 * "ht". Return the value or NULL if the key was not found.
1783 hash_remove_lwpid(hash_table
*ht
, lwpid_t key
)
1790 hash_item_lwpid
*hi
;
1795 if ((bucket
= &(ht
->buckets
[(key
% ht
->num_buckets
)])) != NULL
)
1797 ll
= &(bucket
->list
);
1802 hi
= (hash_item_lwpid
*)li
->datum
;
1806 ll_extract(ll
, li
, lilast
);
1814 li
= LL_NEXT(ll
, li
);
1821 * hash_item_lwpid *hash_first_lwpid(hash_table *ht, hash_pos *pos)
1823 * First function to call when iterating through all items in the hash
1824 * table. Returns the first item in "ht" and initializes "*pos" to track
1825 * the current position.
1829 hash_first_lwpid(hash_table
*ht
, hash_pos
*pos
)
1832 /* initialize pos for first item in first bucket */
1833 pos
->num_buckets
= ht
->num_buckets
;
1834 pos
->hash_bucket
= ht
->buckets
;
1836 pos
->ll_last
= NULL
;
1838 /* find the first non-empty bucket */
1839 while(pos
->hash_bucket
->list
.count
== 0)
1842 if (++pos
->curr
>= pos
->num_buckets
)
1848 /* set and return the first item */
1849 pos
->ll_item
= LL_FIRST(&(pos
->hash_bucket
->list
));
1850 return (hash_item_lwpid
*)pos
->ll_item
->datum
;
1855 * hash_item_lwpid *hash_next_lwpid(hash_pos *pos)
1857 * Return the next item in the hash table, using "pos" as a description
1858 * of the present position in the hash table. "pos" also identifies the
1859 * specific hash table. Return NULL if there are no more elements.
1863 hash_next_lwpid(hash_pos
*pos
)
1868 /* move item to last and check for NULL */
1869 if ((pos
->ll_last
= pos
->ll_item
) == NULL
)
1871 /* are we really at the end of the hash table? */
1872 if (pos
->curr
>= pos
->num_buckets
)
1874 /* yes: return NULL */
1877 /* no: regrab first item in current bucket list (might be NULL) */
1878 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
1882 /* get the next item in the llist */
1883 li
= LL_NEXT(&(pos
->hash_bucket
->list
), pos
->ll_item
);
1886 /* if its NULL we have to find another bucket */
1889 /* locate another bucket */
1890 pos
->ll_last
= NULL
;
1892 /* move to the next one */
1894 if (++pos
->curr
>= pos
->num_buckets
)
1896 /* at the end of the hash table */
1897 pos
->ll_item
= NULL
;
1901 /* get the first element (might be NULL) */
1902 li
= LL_FIRST(&(pos
->hash_bucket
->list
));
1905 /* li is the next element to dish out */
1907 return (hash_item_lwpid
*)li
->datum
;
1911 * void *hash_remove_pos_lwpid(hash_pos *pos)
1913 * Remove the hash table entry pointed to by position marker "pos".
1914 * The data from the entry is returned upon success, otherwise NULL.
1919 hash_remove_pos_lwpid(hash_pos
*pos
)
1924 hash_item_lwpid
*hi
;
1927 if (pos
== NULL
|| pos
->ll_last
== pos
->ll_item
)
1932 /* at this point pos contains the item to remove (ll_item)
1933 and its predecesor (ll_last) */
1934 /* extract the item from the llist */
1936 ll_extract(&(pos
->hash_bucket
->list
), li
, pos
->ll_last
);
1938 /* retain the data */
1939 hi
= (hash_item_lwpid
*)li
->datum
;
1942 /* free up the space */
1945 /* back up to previous item */
1946 /* its okay for ll_item to be null: hash_next will detect it */
1947 pos
->ll_item
= pos
->ll_last
;