HASH_INT hash_tands(HASH_INT triad, hash_table_t *theTable) { hash_cell_t *theElement= theTable->table+hash_hash(triad,theTable); int isScratch; if(theElement->triad == 0)/*No such a triad -- install it and return:*/ return theElement->triad=triad; if(theElement->next == 0){ if( hash_cmp(triad, theElement->triad, theTable) ) return theElement->triad; isScratch=0;/*theElement points somewhere into the table*/ }else{ #ifdef DEBUG HASH_INT maxCNew=0; #endif isScratch=1;/*theElement points somewhere into the scratch*/ for(;;){ if( hash_cmp(triad, theElement->triad, theTable) ) return theElement->triad; if(theElement->next == 0) break; theElement= theTable->scratch+theElement->next; #ifdef DEBUG maxCNew++; #endif }/*for(;;)*/ #ifdef DEBUG nC++; avC+=maxCNew; if(maxCNew>maxC) maxC=maxCNew; #endif }/*else*/ /*Install a new element in scratch:*/ if(theTable->free == theTable->max){/*(re)allocate the scratch array:*/ if(theTable->max == 0) hash_alloc(theTable); else{ if(isScratch){/*theElement points somewhere into the scratch*/ /*Store the position:*/ HASH_INT n=theElement-theTable->scratch; hash_realloc(theTable); /*The scratch was changed, restore the position:*/ theElement=theTable->scratch+n; }else/*theElement has no relation to the scratch, just realloc the scratch:*/ hash_realloc(theTable); }/*else*/ }/*if(theTable->free == theTable->max)*/ /*Install the triad and return:*/ theTable->scratch[theTable->free].triad=triad; theElement->next=theTable->free; theTable->scratch[theTable->free].next=0; theTable->free++; return triad; }/*hash_tands*/
int hash_put( hash_table_t *h, const void *key, const void *data ) { int pos; if( (float)(h->count+1)/h->size > 0.75f ) { if( !hash_realloc( h, (h->size+1) * 2 -1 ) ) { return 0; } } pos = hash_search( h, (void *)key ); if( h->arr[pos].key == 0 ) { h->count++; } h->arr[pos].key = (void *)key; h->arr[pos].data = (void *)data; return 1; }
/** * Add a new frame to the current thread. Resize the stack structure * if necessary. */ static void frame_grow_num_frames() { current_thread->num_frames++; if (current_thread->num_frames >= current_thread->size_frames) { size_t newsize; current_thread->size_frames += 10; newsize = sizeof(thread_info) + current_thread->size_frames * sizeof(frame_info); current_thread = hash_realloc(&threads, 0, newsize); } }
/* * Returns: * 0 ==> OK * -1 ==> Error */ extern int __expand_table(HTAB *hashp) { uint32 old_bucket, new_bucket; int new_segnum, spare_ndx; size_t dirsize; #ifdef HASH_STATISTICS hash_expansions++; #endif new_bucket = ++hashp->MAX_BUCKET; old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); new_segnum = new_bucket >> hashp->SSHIFT; /* Check if we need a new segment */ if (new_segnum >= hashp->nsegs) { /* Check if we need to expand directory */ if (new_segnum >= hashp->DSIZE) { /* Reallocate directory */ dirsize = hashp->DSIZE * sizeof(SEGMENT *); if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) return (-1); hashp->DSIZE = dirsize << 1; } if ((hashp->dir[new_segnum] = (SEGMENT)calloc((size_t)hashp->SGSIZE, sizeof(SEGMENT))) == NULL) return (-1); hashp->exsegs++; hashp->nsegs++; } /* * If the split point is increasing (MAX_BUCKET's log base 2 * * increases), we need to copy the current contents of the spare * split bucket to the next bucket. */ spare_ndx = __log2((uint32)(hashp->MAX_BUCKET + 1)); if (spare_ndx > hashp->OVFL_POINT) { hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; hashp->OVFL_POINT = spare_ndx; } if (new_bucket > (uint32)hashp->HIGH_MASK) { /* Starting a new doubling */ hashp->LOW_MASK = hashp->HIGH_MASK; hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; } /* Relocate records to the new bucket */ return (__split_page(hashp, old_bucket, new_bucket)); }
void hash_remove( hash_table_t *h, const void *key, void **old_key, void **old_val ) { if( !h->count ) { if( old_key != 0 ) *old_key = 0; if( old_val != 0 ) *old_val = 0; return; } int pos = hash_search( h, (void *)key ); int next_pos; if( h->arr[pos].key == 0 ) { if( old_key != 0 ) *old_key = 0; if( old_val != 0 ) *old_val = 0; return; } h->count--; if( old_key != 0 ) *old_key = h->arr[pos].key; if( old_val != 0 ) *old_val = h->arr[pos].data; h->arr[pos].key = 0; next_pos = pos+1; next_pos %= h->size; while( h->arr[next_pos].key != 0 ) { int hv = h->hash_func( h->arr[next_pos].key ); int ideal_pos = ( hv & 0x7fffffff) % h->size; int dist_old = (next_pos - ideal_pos + h->size)%h->size; int dist_new = (pos - ideal_pos + h->size)%h->size; if ( dist_new < dist_old ) { h->arr[pos].key = h->arr[next_pos].key; h->arr[pos].data = h->arr[next_pos].data; h->arr[next_pos].key = 0; pos = next_pos; } next_pos++; next_pos %= h->size; } if( (float)(h->count+1)/h->size < 0.2f && h->count < 63 ) { hash_realloc( h, (h->size+1) / 2 -1 ); } return; }