github.com/phuslu/lru@v1.0.16-0.20240421170520-46288a2fd47c/bytes_shard_table.go (about) 1 // Copyright 2023-2024 Phus Lu. All rights reserved. 2 // Copyright 2019 Joshua J Baker. All rights reserved. 3 // Use of this source code is governed by an ISC-style 4 // license that can be found in the LICENSE file. 5 6 package lru 7 8 import ( 9 "unsafe" 10 ) 11 12 func (s *bytesshard) table_Init(size uint32) { 13 newsize := bytesNewTableSize(size) 14 if len(s.table_buckets) == 0 { 15 s.table_buckets = make([]uint64, newsize) 16 } 17 s.table_mask = newsize - 1 18 s.table_length = 0 19 } 20 21 func bytesNewTableSize(size uint32) (newsize uint32) { 22 newsize = nextPowOf2(size) 23 if float64(newsize)*loadFactor < float64(size) { 24 newsize = nextPowOf2(newsize + 1) 25 } 26 if newsize < 8 { 27 newsize = 8 28 } 29 return 30 } 31 32 // Set assigns an index to a key. 33 // Returns the previous index, or false when no index was assigned. 34 func (s *bytesshard) table_Set(hash uint32, key []byte, index uint32) (prev uint32, ok bool) { 35 subhash := hash >> dibBitSize 36 hdib := subhash<<dibBitSize | uint32(1)&maxDIB 37 mask := s.table_mask 38 i := (hdib >> dibBitSize) & mask 39 b0 := unsafe.Pointer(&s.table_buckets[0]) 40 l0 := unsafe.Pointer(&s.list[0]) 41 for { 42 b := (*bytesbucket)(unsafe.Add(b0, uintptr(i)*8)) 43 if b.hdib&maxDIB == 0 { 44 b.hdib = hdib 45 b.index = index 46 s.table_length++ 47 return 48 } 49 if hdib>>dibBitSize == b.hdib>>dibBitSize && b2s((*bytesnode)(unsafe.Add(l0, uintptr(b.index)*unsafe.Sizeof(s.list[0]))).key) == b2s(key) { 50 prev = b.index 51 b.hdib = hdib 52 b.index = index 53 ok = true 54 return 55 } 56 if b.hdib&maxDIB < hdib&maxDIB { 57 hdib, b.hdib = b.hdib, hdib 58 index, b.index = b.index, index 59 } 60 i = (i + 1) & mask 61 hdib = hdib>>dibBitSize<<dibBitSize | (hdib&maxDIB+1)&maxDIB 62 } 63 } 64 65 // table_Get returns an index for a key. 66 // Returns false when no index has been assign for key. 67 func (s *bytesshard) table_Get(hash uint32, key []byte) (index uint32, ok bool) { 68 subhash := hash >> dibBitSize 69 mask := s.table_mask 70 i := subhash & mask 71 b0 := unsafe.Pointer(&s.table_buckets[0]) 72 l0 := unsafe.Pointer(&s.list[0]) 73 for { 74 b := (*bytesbucket)(unsafe.Add(b0, uintptr(i)*8)) 75 if b.hdib&maxDIB == 0 { 76 return 77 } 78 if b.hdib>>dibBitSize == subhash && b2s((*bytesnode)(unsafe.Add(l0, uintptr(b.index)*unsafe.Sizeof(s.list[0]))).key) == b2s(key) { 79 return b.index, true 80 } 81 i = (i + 1) & mask 82 } 83 } 84 85 // table_Delete deletes an index for a key. 86 // Returns the deleted index, or false when no index was assigned. 87 func (s *bytesshard) table_Delete(hash uint32, key []byte) (index uint32, ok bool) { 88 subhash := hash >> dibBitSize 89 mask := s.table_mask 90 i := subhash & mask 91 b0 := unsafe.Pointer(&s.table_buckets[0]) 92 l0 := unsafe.Pointer(&s.list[0]) 93 for { 94 b := (*bytesbucket)(unsafe.Add(b0, uintptr(i)*8)) 95 if b.hdib&maxDIB == 0 { 96 return 97 } 98 if b.hdib>>dibBitSize == subhash && b2s((*bytesnode)(unsafe.Add(l0, uintptr(b.index)*unsafe.Sizeof(s.list[0]))).key) == b2s(key) { 99 old := b.index 100 s.table_delete(i) 101 return old, true 102 } 103 i = (i + 1) & mask 104 } 105 } 106 107 func (s *bytesshard) table_delete(i uint32) { 108 mask := s.table_mask 109 b0 := unsafe.Pointer(&s.table_buckets[0]) 110 bi := (*bytesbucket)(unsafe.Add(b0, uintptr(i)*8)) 111 bi.hdib = bi.hdib>>dibBitSize<<dibBitSize | uint32(0)&maxDIB 112 for { 113 pi := i 114 i = (i + 1) & mask 115 bpi := (*bytesbucket)(unsafe.Add(b0, uintptr(pi)*8)) 116 bi = (*bytesbucket)(unsafe.Add(b0, uintptr(i)*8)) 117 if bi.hdib&maxDIB <= 1 { 118 bpi.index = 0 119 bpi.hdib = 0 120 break 121 } 122 bpi.index = bi.index 123 bpi.hdib = bi.hdib>>dibBitSize<<dibBitSize | (bi.hdib&maxDIB-1)&maxDIB 124 } 125 s.table_length-- 126 }