// Lookup a cell based on a uint64 key value. Returns nil if key not found. func (t *HashTableSomeStruct) Lookup(key uint64) *CellSomeStruct { var cell *CellSomeStruct if key == 0 { if t.zero().unHashedKey == 1 { return t.zero() } return nil } h := util.IntegerHash(uint64(key)) % t.ArraySize for { cell = t.cellAt(h) if cell.unHashedKey == key { return cell } if cell.unHashedKey == 0 { return nil } h++ if h == t.ArraySize { h = 0 } } }
func (t *HashTableSomeStruct) Insert(key uint64) (*CellSomeStruct, bool) { var cell *CellSomeStruct if key == 0 { zc := t.zero() // inuse isNew := zc.unHashedKey == 0 if isNew { t.Population++ zc.unHashedKey = 1 } return zc, isNew } // if key != 0 { for { h := util.IntegerHash(uint64(key)) % t.ArraySize for { cell = t.cellAt(h) if cell.unHashedKey == key { // already exists return cell, false } if cell.unHashedKey == 0 { if (t.Population+1)*4 >= t.ArraySize*3 { t.Repopulate(t.ArraySize * 2) // resized, so start all over break } t.Population++ cell.unHashedKey = key return cell, true } h++ if h == t.ArraySize { h = 0 } } } }
// DeleteCellSomeStruct deletes the cell pointed to by cell. func (t *HashTableSomeStruct) DeleteCellSomeStruct(cell *CellSomeStruct) { pos := uint64((uintptr(unsafe.Pointer(cell)) - uintptr(unsafe.Pointer(t.cells))) / uintptr(unsafe.Sizeof(CellSomeStruct{}))) // Delete from regular cells if pos < 0 || pos >= t.ArraySize { panic(fmt.Sprintf("cell out of bounds: pos %v was < 0 or >= t.ArraySize == %v", pos, t.ArraySize)) } if t.cellAt(pos).unHashedKey == 0 { panic("zero unHashedKey in non-zero CellSomeStruct!") } // Remove this cell by shuffling neighboring cells so there are no gaps in anyone's probe chain nei := pos + 1 if nei >= t.ArraySize { nei = 0 } var neighbor *CellSomeStruct var circular_offset_ideal_pos int64 var circular_offset_ideal_nei int64 var cellPos *CellSomeStruct for { neighbor = t.cellAt(nei) if neighbor.unHashedKey == 0 { // There's nobody to swap with. Go ahead and clear this cell, then return cellPos = t.cellAt(pos) cellPos.unHashedKey = 0 cellPos.ZeroValue() t.Population-- return } ideal := util.IntegerHash(neighbor.unHashedKey) % t.ArraySize if pos >= ideal { circular_offset_ideal_pos = int64(pos) - int64(ideal) } else { // pos < ideal, so pos - ideal is negative, wrap-around has happened. circular_offset_ideal_pos = int64(t.ArraySize) - int64(ideal) + int64(pos) } if nei >= ideal { circular_offset_ideal_nei = int64(nei) - int64(ideal) } else { // nei < ideal, so nei - ideal is negative, wrap-around has happened. circular_offset_ideal_nei = int64(t.ArraySize) - int64(ideal) + int64(nei) } if circular_offset_ideal_pos < circular_offset_ideal_nei { // Swap with neighbor, then make neighbor the new cell to remove. *t.cellAt(pos) = *neighbor pos = nei } nei++ if nei >= t.ArraySize { nei = 0 } } }