github.com/leslie-fei/fastcache@v0.0.0-20240520092641-b7a9eb05711f/hashmap_bucket.go (about) 1 package fastcache 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 type hashMapBucket struct { 9 len uint32 10 offset uint64 // hashMapBucketElement linkedNode offset 11 } 12 13 func (l *hashMapBucket) Add(base uintptr, node *DataNode) { 14 // 更新list链表, 头插法 15 next := l.offset 16 // 把item的头指针指向当前的listElNode 17 l.offset = node.Offset(base) 18 // 更新next 19 node.Next = next 20 // hashed array len + 1 21 l.len++ 22 } 23 24 func (l *hashMapBucket) Del(prevNode *DataNode, findNode *DataNode) error { 25 // not found 26 if findNode == nil { 27 return ErrNotFound 28 } 29 30 if prevNode == nil { 31 // 就说明这个是头节点, 需要更新list的头节点指向 32 l.offset = findNode.Next 33 } else { 34 prevNode.Next = findNode.Next 35 } 36 37 l.len-- 38 // list中没有任何element, 就把head offset = 0 39 if l.len == 0 { 40 l.offset = 0 41 } 42 43 return nil 44 } 45 46 func (l *hashMapBucket) Reset() { 47 l.len = 0 48 l.offset = 0 49 } 50 51 func (l *hashMapBucket) FindNode(base uintptr, key string) (prevNode *DataNode, findNode *DataNode, findEl *hashMapBucketElement) { 52 if l.len == 0 { 53 return nil, nil, nil 54 } 55 56 offset := l.offset 57 for i := 0; i < int(l.len); i++ { 58 node := ToDataNode(base, offset) 59 el := NodeTo[hashMapBucketElement](node) 60 if el.Equals(key) { 61 findNode = node 62 findEl = el 63 return 64 } 65 prevNode = node 66 offset = node.Next 67 } 68 69 return 70 } 71 72 // hashMapBucketElement key DataNode string + val DataNode []byte 73 type hashMapBucketElement struct { 74 lruNode listNode 75 keyLen uint32 // key length 76 valLen uint32 // val length 77 } 78 79 func (l *hashMapBucketElement) Equals(key string) bool { 80 if l.keyLen != uint32(len(key)) { 81 return false 82 } 83 keyPtr := uintptr(unsafe.Pointer(l)) + sizeOfHashmapBucketElement 84 kh := (*reflect.StringHeader)(unsafe.Pointer(&key)) 85 return memequal(unsafe.Pointer(keyPtr), unsafe.Pointer(kh.Data), uintptr(len(key))) 86 } 87 88 func (l *hashMapBucketElement) UpdateValue(value []byte) { 89 valPtr := uintptr(unsafe.Pointer(l)) + sizeOfHashmapBucketElement + uintptr(l.keyLen) 90 bh := (*reflect.SliceHeader)(unsafe.Pointer(&value)) 91 memmove(unsafe.Pointer(valPtr), unsafe.Pointer(bh.Data), uintptr(len(value))) 92 l.valLen = uint32(len(value)) 93 } 94 95 func (l *hashMapBucketElement) Value() []byte { 96 valPtr := uintptr(unsafe.Pointer(l)) + sizeOfHashmapBucketElement + uintptr(l.keyLen) 97 var ss []byte 98 sh := (*reflect.SliceHeader)(unsafe.Pointer(&ss)) 99 sh.Data = valPtr 100 sh.Len = int(l.valLen) 101 sh.Cap = sh.Len 102 return ss 103 } 104 105 func hashmapElementSize(key string, value []byte) uint64 { 106 return uint64(sizeOfHashmapBucketElement) + uint64(len(key)) + uint64(len(value)) 107 }