X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=blobdiff_plain;f=ston%2Fston_ht.h;h=6ab03e704a0d58f0f6e86626e56622534533c2a7;hp=2d9cb79d2c65a1bf5a8d05ab0f2694f0cbf88be9;hb=HEAD;hpb=6bcbbd2bd3710e13cad79b6822ef93e796d5e105 diff --git a/ston/ston_ht.h b/ston/ston_ht.h index 2d9cb79..6ab03e7 100644 --- a/ston/ston_ht.h +++ b/ston/ston_ht.h @@ -296,37 +296,42 @@ typedef struct ston_dht_header_t }ston_dht_h; typedef struct ston_dht_t -{ ston_dht_h header; - void* (*ht_alloc)(size_t); - void (*ht_free)(void*); - void* bucket_root; - size_t rowsize, bucketsize; +{ ston_dht_h header; + void* (*ht_alloc)(size_t); + void (*ht_free)(void*); + void (*ht_iter)(void*,void*,void*); + void* ht_user_data; + void* bucket_root; + size_t rowsize, bucketsize; }* ston_dht; - +/* STON DHT API + Primary functions for creating hashtables, retrieving pointers to values, + iterating over all keys and values, and destroying hashtables. */ STON_FUNC ston_dht ston_dht_new(uint16_t,uint8_t,void*(*)(size_t),void(*)(void*)); STON_FUNC +void* ston_dht_val(ston_dht,void*); +STON_FUNC ston_dht ston_dht_free(ston_dht); STON_FUNC -void* ston_dht_data(ston_dht,void*); +void ston_dht_iterate(ston_dht,void(*)(void*,void*,void*),void*); +/* Recursive functions intended to be called by other functions, above */ STON_FUNC_STATIC STON_FUNC_NOINLINE void ston_dht_free_bucket(ston_dht,void*); -/* STON_FUNC */ -/* ston_dht ston_dht_iterate_start(ston_dht); */ -/* STON_FUNC */ -/* ston_dht ston_dht_iterate_next(ston_dht); */ - -// Compatibility macros +STON_FUNC_STATIC +STON_FUNC_NOINLINE +void ston_dht_iterate_r(ston_dht,void*); +// Compatibility macros - Deprecated #define ston_dht32_new(_COL,_ALOC,_FRE) (ston_dht_new(4 * _COL, 4, _ALOC, _FRE)) -#define ston_dht32_row(_HT,_K) ((uint32_t*)((uint8_t*)ston_dht_data(_HT,&(_K)) - 4)) +#define ston_dht32_row(_HT,_K) ((uint32_t*)((uint8_t*)ston_dht_val(_HT,&(_K)) - 4)) #define ston_dht32_insertx(_HT,_K,_VP,_OFFS,_N) \ - memcpy((uint32_t*)((uint8_t*)ston_dht_data(_HT,&(_K)) + ((_OFFS - 1) * 4)),_VP,_N * 4) + memcpy((uint32_t*)((uint8_t*)ston_dht_val(_HT,&(_K)) + ((_OFFS - 1) * 4)),_VP,_N * 4) -/* Creates a new bucketted hash table, provided a memory allocation function - that takes a single size_t bytes, a memory free function, a column count, and - a row count which determines the size of the buckets. -*/ +/* New dynamic hashtable, provided value bytes, key bytes, allocator function, + and free function. Value bytes and key bytes are respectively constrained to + uint16 and uint8 so they can be aligned to hashtables encoded for + streaming */ STON_FUNC ston_dht ston_dht_new ( uint16_t val_bytes, @@ -352,12 +357,12 @@ ston_dht ston_dht_new } -/* Returns a pointer to the row of data in the hashtable containing the provided - key, inserting if not found, or NULL if a memory error occurs */ +/* Returns a pointer to the value in the hashtable matching the provided key, + inserting if not found, or NULL if a memory error occurs */ STON_FUNC -void* ston_dht_data +void* ston_dht_val ( struct ston_dht_t* ht, - void* key + void* key ) { size_t key_bytes = ht->header.key_bytes; uint8_t* key_byte = (uint8_t*)key; @@ -394,7 +399,8 @@ void* ston_dht_data return (void*) row + sizeof(void*) + key_bytes; } -/* Free the dynamic hash table */ +/* Recursively frees all memory stored in the hashtable, and the hashtable + itself */ STON_FUNC struct ston_dht_t* ston_dht_free ( struct ston_dht_t* ht ) @@ -406,24 +412,54 @@ struct ston_dht_t* ston_dht_free return ht; } -/* Recursively free pages by lookup */ +/* Recursive free function for nested buckets */ STON_FUNC_STATIC STON_FUNC_NOINLINE void ston_dht_free_bucket ( struct ston_dht_t* ht, - void* bucket + void* bucket ) -{ size_t key_bytes = ht->header.key_bytes; - size_t val_bytes = ht->header.val_bytes; - void** bucket_cur = (void**)((uint8_t*)bucket); - void** bucket_max = (void**)((uint8_t*)bucket_cur + ((sizeof(void*) + key_bytes + val_bytes) * 0x100)); +{ void** bucket_cur = (void**)((uint8_t*)bucket); + void** bucket_max = (void**)((uint8_t*)bucket_cur + (ht->rowsize * 0x100)); while (bucket_cur < bucket_max) { if (*bucket_cur != NULL) ston_dht_free_bucket(ht, *bucket_cur); - bucket_cur = (void**)((uint8_t*)bucket_cur + sizeof(void*) + key_bytes + val_bytes); + bucket_cur = (void**)((uint8_t*)bucket_cur + ht->rowsize); } ht->ht_free(bucket); } +/* Iterate over each key/value pair and execut 'fn' with key, value and + user_data as its arguments. user_data may be anything, even NULL, and is + expected to be referenced inside the body of 'fn' as the third argument of + 'fn' */ +STON_FUNC +void ston_dht_iterate +( struct ston_dht_t* ht, + void (*fn)(void*,void*,void*), + void* user_data +) +{ ht->ht_iter = fn; + ht->ht_user_data = user_data; + ston_dht_iterate_r(ht,ht->bucket_root); +} + +/* Recursively iterate through the given bucket belonging to hashtable ht */ +STON_FUNC_STATIC +STON_FUNC_NOINLINE +void ston_dht_iterate_r +( struct ston_dht_t* ht, + void* bucket +) +{ uint8_t* row = (uint8_t*)bucket; + uint8_t* row_max = (row + (ht->rowsize * 0x100)); + while (row < row_max) + { if (*(void**)row != NULL) + ston_dht_iterate_r(ht, *(void**)row); + row += sizeof(void*); + ht->ht_iter((void*)row, (void*)(row + ht->header.key_bytes),ht->ht_user_data); + row += ht->header.key_bytes + ht->header.val_bytes; + } +} #endif //_STON_HT_H_