/* $Source: bitbucket.org:berkeleylab/gasnet.git/extended-ref/coll/gasnet_hashtable.c $ * Description: Reference implemetation of GASNet Collectives team * Copyright 2009, The Regents of the University of California * Terms of use are as specified in license.txt */ /** * Implement hash table data structure using vectors (chaining) to * solve collisions * * For information about the data structures and algorithms used in the * implementation, please see Ch. 12 of Introduction to Algorithms * by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest. * * Lawrence Berkeley National Laboratory * 2009 */ #include #include #include #include /* Part I: table */ gasnete_table_t * gasnete_table_create(uint32_t size) { gasnete_table_t * table; gasneti_assert(size > 0); table = (gasnete_table_t *)gasneti_malloc(sizeof(gasnete_table_t)); table->slots = (gasnete_table_item_t *)gasneti_malloc(sizeof(gasnete_table_item_t)*size); table->size = size; table->num = 0; return table; } gasnete_table_item_t * gasnete_table_search(const gasnete_table_t * const table, uint32_t key) { uint32_t i; gasnete_table_item_t * slots; gasneti_assert(table != NULL); slots = table->slots; for (i=0; inum; i++) if (key == slots[i].key) return &slots[i]; return NULL; /* item with key is not found in the table */ } uint32_t gasnete_table_insert(gasnete_table_t * const table, gasnete_table_item_t item) { if (table->num >= table->size) return 1; /* insertion failed because the table is full */ /* added the item to the end of the table */ table->slots[table->num] = item; table->num++; return 0; /* success */ } uint32_t gasnete_table_remove(gasnete_table_t * const table, uint32_t key, gasnete_table_item_t * deleted) { gasnete_table_item_t item; uint32_t i; gasnete_table_item_t * slots; gasneti_assert(table != NULL); slots = table->slots; for (i=0; inum; i++) if (key == slots[i].key) { item = table->slots[i]; if (deleted != NULL) { deleted->key = item.key; deleted->data = item.data; } if (i < table->num-1) table->slots[i] = table->slots[table->num-1]; table->num--; return 0; } #ifdef DEBUG gasneti_console_message("WARNING","gasnete_table_remove() trying to remove an item not in the table!"); #endif return 1; /* item not in the table */ } void gasnete_table_copy(const gasnete_table_t * const src, gasnete_table_t * const dst) { uint32_t i; gasnete_table_item_t * src_slots, * dst_slots; gasneti_assert(dst->size >= src->num); src_slots = src->slots; dst_slots = dst->slots; for (i=0; inum; i++) dst_slots[i] = src_slots[i]; dst->num = src->num; } void gasnete_table_free(gasnete_table_t * const table) { gasneti_assert(table != NULL); gasneti_free(table->slots); gasneti_free(table); } /* Part II: hashtable build over table */ #define TABLE_INIT_SIZE 10 gasnete_hashtable_t * gasnete_hashtable_create(uint32_t size) { gasnete_hashtable_t * ht; uint32_t i; gasneti_assert(size > 0); ht = (gasnete_hashtable_t *)gasneti_malloc(sizeof(gasnete_hashtable_t)); ht->buckets = (gasnete_table_t **)gasneti_malloc(sizeof(gasnete_table_t *)*size); ht->size = size; ht->num = 0; for (i=0; ibuckets[i] = gasnete_table_create(TABLE_INIT_SIZE); gasneti_assert(ht->buckets[i] != NULL); } return ht; } void gasnete_hashtable_free(gasnete_hashtable_t * ht) { uint32_t i; gasneti_assert(ht != NULL); gasneti_assert(ht->buckets != NULL); for (i=0; isize; i++) { gasneti_assert(ht->buckets[i] != NULL); gasnete_table_free(ht->buckets[i]); } gasneti_free(ht->buckets); gasneti_free(ht); } uint32_t gasnete_hashtable_search(gasnete_hashtable_t * ht, uint32_t key, void ** data) { gasnete_table_t * table; gasnete_table_item_t * item; gasneti_assert(ht != NULL); table = ht->buckets[gasnete_hashtable_hash(ht, key)]; gasneti_assert (table != NULL); item = gasnete_table_search(table, key); if (item == NULL) return 1; /* cannot find the item with key */ if (data != NULL) *data = item->data; return 0; /* success */ } uint32_t gasnete_hashtable_insert(gasnete_hashtable_t * ht, uint32_t key, void * data) { gasnete_table_t * table; gasnete_table_item_t item; uint32_t i; gasneti_assert(ht != NULL); item.key = key; item.data = data; i = gasnete_hashtable_hash(ht, key); table = ht->buckets[i]; gasneti_assert (table != NULL); /* double the size of the table if the table is full */ if (table->num == table->size) { gasnete_table_t * new_table; new_table = gasnete_table_create(table->size*2); gasneti_assert(new_table != NULL); gasnete_table_copy(table, new_table); ht->buckets[i] = new_table; gasnete_table_free(table); table = new_table; } ht->num++; return gasnete_table_insert(table, item); } uint32_t gasnete_hashtable_remove(gasnete_hashtable_t * ht, uint32_t key, void ** data) { gasnete_table_t * table; gasnete_table_item_t item; uint32_t i, rv; gasneti_assert(ht != NULL); i = gasnete_hashtable_hash(ht, key); table = ht->buckets[i]; gasneti_assert (table != NULL); if (table == NULL) return 1; rv = gasnete_table_remove(table, key, &item); if (rv == 0 && data != NULL) *data = item.data; ht->num--; return rv; }