void *ht_remove_fa(hashtable *ht, const void *key, void (*free_key)(void*), const void *hash_arg, const void *cmp_arg) { hash_t k; int res; void *data; if (!ht || !key) return NULL; k = ht->hash(key, hash_arg) % ht->n_buckets; res = htbucket_remove(ht->buckets + k, &data, key, ht->cmp, cmp_arg, free_key); if (res == HT_OK) { ht->n_items--; /* items < buckets/4 -> resize */ if (ht->n_items * 4 < ht->n_buckets) ht_resize(ht, 0); return data; } return NULL; }
SExp make_hash_table(void) { SHash* p = smalloc(sizeof(*p), FALSE); p->typeinfo = &TSHash; ht_init(&p->ht, &SHashVTbl); ht_resize(&p->ht, 129); return ptr2s(p); }
int GrHash_MapWithNewKey(GrHash* h,GrObject* key,GrObject* value) { assert(value); ssize_t code=GrObject_Hash(key); ssize_t used=h->h_used; int ret=0; GrHashEntry* p=h->h_look_up(h,key,code); if(p==NULL) { return -1; } if(p->e_key==NULL) { h->h_fill++; h->h_used++; } if(p->e_key==Gr_Hash_Dummy) { h->h_used++; } p->e_key=key; p->e_value=value; p->e_code=code; /* check space, make sure 1/3 free slot */ if(used<h->h_used && h->h_fill*3 >h->h_mask*2) { ret=ht_resize(h,(h->h_used>50000?2:4)*h->h_used); } GrGc_Intercept(h,key); GrGc_Intercept(h,value); return ret; }
/** * ht_insert(htable *table, ht_entry *entry) * * Insert entry into table. * Returns the inserted entry. **/ ht_entry *ht_insert(htable *table, ht_entry *entry) { // Get the bucket that the entry hashes to. long bucket = (*table->hash)(entry->key) % table->length; // Get the chain for that bucket. ht_entry *chain = table->array[bucket].datum; // Put our new entry at the head of the chain. // If the chain does not yet exist, then create // it starting with our new entry. if (! chain) { chain = entry; entry->next = NULL; entry->prev = NULL; table->array[bucket].datum = chain; } else { entry->next = chain; entry->prev = NULL; chain->prev = entry; table->array[bucket].datum = entry; chain = entry; } table->size++; table->array[bucket].length++; // Check to see if the table should be resized. ht_resize(table); // Return the head of the chain. return chain; }
// Insert htelem struct into hash table int ht_ins_htelem(hashtab *ht, htelem *htelem) { unsigned hash = ht->hash(htelem->key); hash = hash % ht->asize; struct htelem *p; struct htelem *start = ht->array[hash]; for(p = start; p != NULL; p = p->next) { if(ht->keyEqual(p->key, htelem->key)) { ht->freeElem(p->elem); ht->freeKey(htelem->key); p->elem = htelem->elem; free(htelem); return 0; } } // Not found in hash table, add to front of linked list p = start; ht->array[hash] = htelem; htelem->next = p; ht->members++; if((float)ht->members / (float)ht->asize > MAX_LOAD_FACTOR) if(ht_resize(ht) < 0) return -1; return 0; }
//~~~~~~~~~~~~~~~~~MAIN~~~~~~~~~~~~~~~~~~~~~~~ int main(int argc, char* argv[]){ int debug = 0, flag = 1, arg, numRead = 0; char command, *stream; Line line = line_init( stdin); gen_parse_args( argc, argv, &debug); Htable htable = ht_init( ht_mod_hash); while(flag){ arg = -1; fprintf( stdout, "\ncommand: "); line_read_line( line); stream = get_line( line); sscanf( stream, " %c%n", &command, &numRead); switch( command){ case 'q': flag = 0; break; case 'i': sscanf( stream+numRead, "%d", &arg); if( arg < 0) fprintf( stderr, "MUST BE >= 0\n"); else ht_add( htable, arg, arg, debug); break; case 'd': sscanf( stream+numRead, "%d", &arg); if( arg < 0) fprintf( stderr, "MUST BE >= 0\n"); else{ int pos = ht_mod_hash( htable, arg); node_delete( &((htable->table)[pos]), arg, arg, debug); } break; case 'c': sscanf( stream+numRead, "%d", &arg); if( arg < 0) fprintf( stderr, "MUST BE >= 0\n"); else{ if( ht_exists( htable, arg, debug) ) fprintf( stdout, "The value, %d, exists!\n", arg); else fprintf( stdout, "The value, %d, does NOT exist\n", arg); } break; case 'e': ht_erase( htable); break; case 'r': sscanf( stream+numRead, "%d", &arg); if( arg >= 1) ht_resize( htable, arg, debug); else fprintf( stderr, "Error, size must be >= 1\n"); break; case 'l': ht_list( htable); break; case '\n': break; default: fprintf( stdout, "Sorry, Invalid command\n"); break; } free(stream); } line_free( line); ht_free( htable); return 0; }
int main(void) { printf("*****testing hash table*****\n\n"); htbl* t = ht_new(&good_hash, 10); FILE* cnets2015 = fopen("cnets2015", "r"); while (!feof(cnets2015)) { char* s = alloc_str(256); fgets(s, 256, cnets2015); char* l = trim_newline(s); free(s); if (strlen(l) > 0) { ht_ins(l, t); } free(l); } fclose(cnets2015); ht_show(t); printf("The hash table has %u buckets with %u entries (load factor %lg).\n\n", t->n_buckets, ht_n_entries(t), ht_load_factor(t)); printf("The bucket with the most items in it contains %u items.\n\n", ht_max_bucket(t)); printf("ht_member:\n"); printf("membership of cnet \"aardvark\" : %i\n", ht_member("aardvark", t)); printf("membership of cnet \"borja\" : %i\n", ht_member("borja", t)); printf("\n"); // resize printf("***now resizing***\n"); ht_resize(&t); printf("***resizing complete***\n\n"); // do everything again ht_show(t); printf("The hash table has %u buckets with %u entries (load factor %lg).\n\n", t->n_buckets, ht_n_entries(t), ht_load_factor(t)); printf("The bucket with the most items in it contains %u items.\n\n", ht_max_bucket(t)); printf("ht_member:\n"); printf("membership of cnet \"aardvark\" : %i\n", ht_member("aardvark", t)); printf("membership of cnet \"borja\" : %i\n", ht_member("borja", t)); printf("\n"); ht_free(t); return 0; }
t_value *ht_update(t_hash_table *h, t_key key) { int hash = ht_hash(key, h->size); t_bucket *b = ht_find_bucket(h, key, hash); t_value value; value.ull = 0ULL; if (b == NULL) { if (h->num_keys == h->size) { ht_resize(h); hash = ht_hash(key, h->size); } b = ht_create_bucket(h, key, value, h->bucket_ptrs[hash]); h->bucket_ptrs[hash] = b; } return &(b->value); }
int ht_insert_a(hashtable *ht, void *key, void *data, const void *hash_arg, const void *cmp_arg) { int res; hash_t k; if (!ht || !key) return HT_ERROR; k = ht->hash(key, hash_arg) % ht->n_buckets; res = htbucket_insert(ht->buckets + k, key, data, ht->cmp, cmp_arg); if (res == HT_OK) { ht->n_items++; if (ht->n_items > ht->n_buckets) ht_resize(ht, 1); } return res; }
void ht_insert(smb_ht *table, DATA key, DATA value) { unsigned int index; if (ht_load_factor(table) >= HASH_TABLE_MAX_LOAD_FACTOR) { ht_resize(table); } // First, probe for the key as if we're trying to return it. If we find it, // we update the existing key. index = ht_find_retrieve(table, key); if (table->table[index].mark == HT_FULL) { table->table[index].value = value; return; } // If we don't find the key, then we find the first open slot or gravestone. index = ht_find_insert(table, key); table->table[index].key = key; table->table[index].value = value; table->table[index].mark = HT_FULL; table->length++; }
/* doc: <routine name="ht_safe_force" return_type="int" export="shared"> doc: <summary>Put value `val' associated with key `key' in table `ht'. If `ht' is full, we will resize `ht' and try again. If `resizing' failed or if we cannot find a suitable position, a negative value is returned.</summary> doc: <param name="ht" type="struct htable *">Table to initialize.</param> doc: <param name="key" type="rt_uint_ptr">Key to insert in `ht'.</param> doc: <param name="val" type="void *">Value to insert in `ht'.</param> doc: <return>0 upon successful insertion, -1 if cannot resize, -2 if cannot insert.</return> doc: <thread_safety>Not Safe</thread_safety> doc: <synchronization>None</synchronization> doc: </routine> */ rt_shared int ht_safe_force (struct htable *ht, rt_uint_ptr key, void * val) { REQUIRE("ht not null", ht); REQUIRE("key not null", key); if (!(ht_put(ht, key, val))) { /* Insertion failed => H table full */ /* Resize the hash table */ if (ht_resize(ht, ht->h_capacity + (ht->h_capacity / 2))) { /* Cannot resize. */ return -1; } else { /* Something (...) was rotten, don't know what */ /* Insertion failed again => Bailing out */ if (!(ht_put(ht, key, val))) { /* Cannot insert. */ return -2; } } } /* Success. */ return 0; }
// this was separated out of the regular ht_insert // for ease of copying hash entries around void ht_insert_he(hash_table *table, hash_entry *entry){ hash_entry *tmp; unsigned int index; entry->next = NULL; index = ht_index(table, entry->key, entry->key_size); tmp = table->array[index]; // if true, no collision if(tmp == NULL) { table->array[index] = entry; table->key_count++; return; } // walk down the chain until we either hit the end // or find an identical key (in which case we replace // the value) int count = 1; while(tmp->next != NULL) { count++; if(he_key_compare(tmp, entry)) break; else tmp = tmp->next; } if(he_key_compare(tmp, entry)) { // if the keys are identical, throw away the old entry // and stick the new one into the table he_set_value(table->flags, tmp, entry->value, entry->value_size); he_destroy(table->flags, entry); } else { // else tack the new entry onto the end of the chain tmp->next = entry; table->collisions += 1; table->key_count ++; table->current_load_factor = (double)table->collisions / table->array_size; //保存哈希表中发生冲突最多的下标和数目, 便于观察和修改resize的策略 if (count > table->max_collisions) { table->max_collisions = count; table->max_collisions_index = index; } // double the size of the table if autoresize is on and the // load factor has gone too high // add max_collisions condition ? if (!(table->flags & HT_NO_AUTORESIZE) && (table->current_load_factor > table->max_load_factor) && (table->max_collisions > 10)) //if (!(table->flags & HT_NO_AUTORESIZE) && (table->current_load_factor > table->max_load_factor)) { debug("max_index is %d, max_collisions is %d \n", table->max_collisions_index, table->collisions); ht_resize(table, table->array_size * 2); table->current_load_factor = (double)table->collisions / table->array_size; } } }
void ht_term(HashTable* ht) { ht_resize(ht, 0); }
void *test_hash_rw_thr_writer(void *_count) { struct lfht_test_node *node; struct cds_lfht_node *ret_node; struct cds_lfht_iter iter; struct wr_count *count = _count; int ret; printf_verbose("thread_begin %s, tid %lu\n", "writer", urcu_get_thread_id()); URCU_TLS(rand_lookup) = urcu_get_thread_id() ^ time(NULL); set_affinity(); rcu_register_thread(); while (!test_go) { } cmm_smp_mb(); for (;;) { if ((addremove == AR_ADD || add_only) || (addremove == AR_RANDOM && rand_r(&URCU_TLS(rand_lookup)) & 1)) { node = malloc(sizeof(struct lfht_test_node)); lfht_test_node_init(node, (void *)(((unsigned long) rand_r(&URCU_TLS(rand_lookup)) % write_pool_size) + write_pool_offset), sizeof(void *)); rcu_read_lock(); if (add_unique) { ret_node = cds_lfht_add_unique(test_ht, test_hash(node->key, node->key_len, TEST_HASH_SEED), test_match, node->key, &node->node); } else { if (add_replace) ret_node = cds_lfht_add_replace(test_ht, test_hash(node->key, node->key_len, TEST_HASH_SEED), test_match, node->key, &node->node); else cds_lfht_add(test_ht, test_hash(node->key, node->key_len, TEST_HASH_SEED), &node->node); } rcu_read_unlock(); if (add_unique && ret_node != &node->node) { free(node); URCU_TLS(nr_addexist)++; } else { if (add_replace && ret_node) { call_rcu(&to_test_node(ret_node)->head, free_node_cb); URCU_TLS(nr_addexist)++; } else { URCU_TLS(nr_add)++; } } } else { /* May delete */ rcu_read_lock(); cds_lfht_test_lookup(test_ht, (void *)(((unsigned long) rand_r(&URCU_TLS(rand_lookup)) % write_pool_size) + write_pool_offset), sizeof(void *), &iter); ret = cds_lfht_del(test_ht, cds_lfht_iter_get_node(&iter)); rcu_read_unlock(); if (ret == 0) { node = cds_lfht_iter_get_test_node(&iter); call_rcu(&node->head, free_node_cb); URCU_TLS(nr_del)++; } else URCU_TLS(nr_delnoent)++; } #if 0 //if (URCU_TLS(nr_writes) % 100000 == 0) { if (URCU_TLS(nr_writes) % 1000 == 0) { rcu_read_lock(); if (rand_r(&URCU_TLS(rand_lookup)) & 1) { ht_resize(test_ht, 1); } else { ht_resize(test_ht, -1); } rcu_read_unlock(); } #endif //0 URCU_TLS(nr_writes)++; if (caa_unlikely(!test_duration_write())) break; if (caa_unlikely(wdelay)) loop_sleep(wdelay); if (caa_unlikely((URCU_TLS(nr_writes) & ((1 << 10) - 1)) == 0)) rcu_quiescent_state(); } rcu_unregister_thread(); printf_verbose("thread_end %s, tid %lu\n", "writer", urcu_get_thread_id()); printf_verbose("info tid %lu: nr_add %lu, nr_addexist %lu, nr_del %lu, " "nr_delnoent %lu\n", urcu_get_thread_id(), URCU_TLS(nr_add), URCU_TLS(nr_addexist), URCU_TLS(nr_del), URCU_TLS(nr_delnoent)); count->update_ops = URCU_TLS(nr_writes); count->add = URCU_TLS(nr_add); count->add_exist = URCU_TLS(nr_addexist); count->remove = URCU_TLS(nr_del); return ((void*)2); }
void init_symbol_table(void) { ht_init(&s_symbol_table, &SymbolHTVTbl); ht_resize(&s_symbol_table, 129); }
int main(int argc, char *argv[]) { (void) argc; (void) argv; hash_table ht; ht_init(&ht, HT_KEY_CONST | HT_VALUE_CONST, 0.05); char *s1 = (char*)"teststring 1"; char *s2 = (char*)"teststring 2"; char *s3 = (char*)"teststring 3"; ht_insert(&ht, s1, strlen(s1)+1, s2, strlen(s2)+1); int contains = ht_contains(&ht, s1, strlen(s1)+1); test(contains, "Checking for key \"%s\"", s1); size_t value_size; char *got = ht_get(&ht, s1, strlen(s1)+1, &value_size); fprintf(stderr, "Value size: %zu\n", value_size); fprintf(stderr, "Got: {\"%s\": -----\"%s\"}\n", s1, got); test(value_size == strlen(s2)+1, "Value size was %zu (desired %lu)", value_size, strlen(s2)+1); fprintf(stderr, "Replacing {\"%s\": \"%s\"} with {\"%s\": \"%s\"}\n", s1, s2, s1, s3); ht_insert(&ht, s1, strlen(s1)+1, s3, strlen(s3)+1); unsigned int num_keys; void **keys; keys = ht_keys(&ht, &num_keys); test(num_keys == 1, "HashTable has %d keys", num_keys); test(keys != NULL, "Keys is not null"); if(keys) free(keys); got = ht_get(&ht, s1, strlen(s1)+1, &value_size); fprintf(stderr, "Value size: %zu\n", value_size); fprintf(stderr, "Got: {\"%s\": \"%s\"}\n", s1, got); test(value_size == strlen(s3)+1, "Value size was %zu (desired %lu)", value_size, strlen(s3)+1); fprintf(stderr, "Removing entry with key \"%s\"\n", s1); ht_remove(&ht, s1, strlen(s1)+1); contains = ht_contains(&ht, s1, strlen(s1)+1); test(!contains, "Checking for removal of key \"%s\"", s1); keys = ht_keys(&ht, &num_keys); test(num_keys == 0, "HashTable has %d keys", num_keys); if(keys) free(keys); fprintf(stderr, "Stress test"); int key_count = 1000000; int i; int *many_keys = malloc(key_count * sizeof(*many_keys)); int *many_values = malloc(key_count * sizeof(*many_values)); srand(time(NULL)); for(i = 0; i < key_count; i++) { many_keys[i] = i; many_values[i] = rand(); } struct timespec t1; struct timespec t2; t1 = snap_time(); for(i = 0; i < key_count; i++) { ht_insert(&ht, &(many_keys[i]), sizeof(many_keys[i]), &(many_values[i]), sizeof(many_values[i])); } t2 = snap_time(); fprintf(stderr, "Inserting %d keys took %.2f seconds\n", key_count, get_elapsed(t1, t2)); fprintf(stderr, "Checking inserted keys\n"); int ok_flag = 1; for(i = 0; i < key_count; i++) { if(ht_contains(&ht, &(many_keys[i]), sizeof(many_keys[i]))) { size_t value_size; int value; value = *(int*)ht_get(&ht, &(many_keys[i]), sizeof(many_keys[i]), &value_size); if(value != many_values[i]) { fprintf(stderr, "Key value mismatch. Got {%d: %d} expected: {%d: %d}\n", many_keys[i], value, many_keys[i], many_values[i]); ok_flag = 0; break; } } else { fprintf(stderr, "Missing key-value pair {%d: %d}\n", many_keys[i], many_values[i]); ok_flag = 0; break; } } test(ok_flag == 1, "Result was %d", ok_flag); ht_clear(&ht); ht_resize(&ht, 4194304); t1 = snap_time(); for(i = 0; i < key_count; i++) { ht_insert(&ht, &(many_keys[i]), sizeof(many_keys[i]), &(many_values[i]), sizeof(many_values[i])); } t2 = snap_time(); fprintf(stderr, "Inserting %d keys (on preallocated table) took %.2f seconds\n", key_count, get_elapsed(t1, t2)); for(i = 0; i < key_count; i++) { ht_remove(&ht, &(many_keys[i]), sizeof(many_keys[i])); } test(ht_size(&ht) == 0, "%d keys remaining", ht_size(&ht)); ht_destroy(&ht); free(many_keys); free(many_values); return report_results(); }