| 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 this regions.
This hash doesn't move during GC, therefore a lot of the old caveats don't apply.

static size_t key_hash_STRING(Interp *interp, void *value, size_t seed)value.static int STRING_compare(Parrot_Interp interp, void *a, void *b)a is the search key,
b is the bucket key.static int pointer_compare(Parrot_Interp interp, void *a, void *b)static size_t key_hash_pointer(Interp *interp, void *value, size_t seed)static size_t key_hash_cstring(Interp *interp, void *value, size_t seed)static int cstring_compare(Parrot_Interp interp, void *a, void *b)key_hash and compare functions.static size_t key_hash_int(Interp *interp, void *value, size_t seed)static int int_compare(Parrot_Interp interp, void *a, void *b)key_hash and compare functions.void parrot_dump_hash(Interp *interp, Hash *hash)void parrot_mark_hash(Interp *interp, Hash *hash)void parrot_hash_visit(Interp *interp, Hash *hash, void *pinfo)pinfo is the visit info,
(see include/parrot/pmc_freeze.h>).static void expand_hash(Interp *interp, Hash *hash)MAXFULL_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. bucket_index = hash(key) % parrot_hash_size
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.->next pointers, and they'll be all over memory.)void parrot_new_hash(Interp *interp, Hash **hptr)hptr.void parrot_new_cstring_hash(Interp *interp, Hash **hptr)hptr.void parrot_new_hash_x(Interp *interp, Hash **hptr, PARROT_DATA_TYPES val_type, Hash_key_type hkey_type, hash_comp_fn compare, hash_hash_key_fn keyhash)hptr.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_x(Interp *interp, PMC *container, PARROT_DATA_TYPES val_type, Hash_key_type hkey_type, hash_comp_fn compare, hash_hash_key_fn keyhash)container PMC gets stored in the Hash end the newly created Hash is in PMC_struct_val(container).void parrot_new_pointer_hash(Interp *interp, Hash **hptr)PMC *Parrot_new_INTVAL_hash(Interp *interp, UINTVAL flags)flags can be PObj_constant_FLAG or 0.INTVAL parrot_hash_size(Interp *interp, Hash *hash)void *parrot_hash_get_idx(Interp *interp, Hash *hash, PMC *key)HashBucket *parrot_hash_get_bucket(Interp *interp, Hash *hash, void *key)key.void *parrot_hash_get(Interp *interp, Hash *hash, void *key)key or NULL if no bucket is found.INTVAL parrot_hash_exists(Interp *interp, Hash *hash, void *key)HashBucket *parrot_hash_put(Interp *interp, Hash *hash, void *key, void *value)key is not copied.void parrot_hash_delete(Interp *interp, Hash *hash, void *key)void parrot_hash_clone(Interp *interp, Hash *hash, Hash **dest)hash to dest.
docs/pdds/pdd08_keys.pod.

leo add function pointer for compare, hash, mark
hash keys are now (void *)
add parrot_new_cstring_hash() function
bucket->value is now a plain pointer, no more an HASH_ENTRY
With little changes, we can again store arbitrary items if needed, see TODO in code.
boemmels renamed HASH and HASHBUCKET to Hash and HashBucket
leo randomize key_hash seed
extend parrot_new_hash_x() init call by value_type and _size.
leo USE_STRING_EQUAL define, see comment above
leo heavy rewrite: use just one piece of malloced memory

Future optimizations:
realloc.)
|
|
|