| parrotcode: Hash table | |
| Contents | C |

src/hash.c - Hash table

A hashtable contains an array of bucket indexes.
Buckets are nodes in a linked list,
each containing a void * key and value.
During hash creation,
the types of key and value as well as appropriate compare and hashing functions can be set.
This hash implementation uses just one piece of malloced memory.
The hash->bs bucket store points to this region.
This hash doesn't move during GC, therefore a lot of the old caveats don't apply.

static size_t key_hash_STRINGvalue.
See also string.c.
static int STRING_comparestatic int pointer_comparestatic size_t key_hash_pointerstatic size_t key_hash_cstringstatic int cstring_comparekey_hash and compare functions.
size_t key_hash_intkey_hash function.
int int_comparecompare function.
void parrot_dump_hashvoid parrot_mark_hashstatic void hash_thawpinfo is the visit info,
(see include/parrot/pmc_freeze.h>).
static void hash_freezevoid parrot_hash_visitstatic void expand_hashMAXFULL_PERCENT % of N as the number of buckets.
This way,
as soon as we run out of buckets on the free list,
we know that it's time to resize the hashtable.Algorithm for expansion: We exactly double the size of the hashtable.
Keys are assigned to buckets with the formula
bucket_index = hash(key) % parrot_hash_sizeso when doubling the size of the hashtable, we know that every key is either already in the correct bucket, or belongs in the current bucket plus
parrot_hash_size (the old parrot_hash_size). In fact, because the hashtable is always a power of two in size, it depends only on the next bit in the hash value, after the ones previously used.So we scan through all the buckets in order, moving the buckets that need to be moved. No bucket will be scanned twice, and the cache should be reasonably happy because the hashtable accesses will be two parallel sequential scans. (Of course, this also mucks with the ->next pointers, and they'll be all over memory.)
void parrot_new_hashhptr.
void parrot_new_pmc_hashvoid parrot_new_cstring_hashhptr.
static Hash *create_hashvoid parrot_hash_destroyvoid parrot_chash_destroyvoid parrot_chash_destroy_valuesvoid and takes a void *.
void parrot_new_hash_xhptr.FIXME: This function can go back to just returning the hash struct pointer once Buffers can define their own custom mark routines.The problem is: During DODs stack walking the item on the stack must be a PMC. When an auto Hash* is seen, it doesn't get properly marked (only the Hash* buffer is marked, not its contents). By passing the **hptr up to the Hash's init function, the newly constructed PMC is on the stack including this newly constructed Hash, so that it gets marked properly.
void parrot_new_pmc_hash_xcontainer PMC gets stored in the Hash end the newly created Hash is in PMC_struct_val(container).
void parrot_new_pointer_hashPMC *Parrot_new_INTVAL_hashflags can be PObj_constant_FLAG or 0.
INTVAL parrot_hash_sizevoid *parrot_hash_get_idxHashBucket *parrot_hash_get_bucketkey.
void *parrot_hash_getkey or NULL if no bucket is found.
INTVAL parrot_hash_existsHashBucket *parrot_hash_putkey is not copied.
void parrot_hash_deletevoid parrot_hash_clonehash to dest.
docs/pdds/pdd08_keys.pod.

Future optimizations:
realloc.)
|
|
|