github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/skl/lf/arena.go (about) 1 package lf 2 3 import ( 4 "errors" 5 "sync/atomic" 6 "unsafe" 7 8 "github.com/zhiqiangxu/util/bytes" 9 ) 10 11 // Arena is lock free 12 type Arena struct { 13 n uint32 14 buf []byte 15 } 16 17 var ( 18 // ErrOOM used by Arena 19 ErrOOM = errors.New("oom") 20 ) 21 22 // NewArena is ctor for Arena 23 func NewArena(n uint32) *Arena { 24 25 // offset 0 is reserved for nil value 26 out := &Arena{n: 1, buf: bytes.AlignedTo8(n)} 27 28 return out 29 } 30 31 func (a *Arena) putKV(k, v []byte) (koff, voff uint32, err error) { 32 lk := uint32(len(k)) 33 lv := uint32(len(v)) 34 l := lk + lv 35 n := atomic.AddUint32(&a.n, l) 36 if int(n) > len(a.buf) { 37 err = ErrOOM 38 return 39 } 40 41 koff = n - l 42 copy(a.buf[koff:koff+lk], k) 43 voff = koff + lk 44 copy(a.buf[voff:voff+lv], v) 45 return 46 } 47 48 func (a *Arena) putBytes(b []byte) (offset uint32, err error) { 49 l := uint32(len(b)) 50 n := atomic.AddUint32(&a.n, l) 51 if int(n) > len(a.buf) { 52 err = ErrOOM 53 return 54 } 55 56 offset = n - l 57 copy(a.buf[offset:n], b) 58 return 59 60 } 61 62 const ( 63 nodeAlign = int(unsafe.Sizeof(uint64(0))) - 1 64 ) 65 66 func (a *Arena) putListNode() (offset uint32, err error) { 67 68 // Pad the allocation with enough bytes to ensure pointer alignment. 69 l := uint32(ListNodeSize + nodeAlign) 70 n := atomic.AddUint32(&a.n, l) 71 if int(n) > len(a.buf) { 72 err = ErrOOM 73 return 74 } 75 76 // Return the aligned offset. 77 offset = (n - l + uint32(nodeAlign)) & ^uint32(nodeAlign) 78 return 79 } 80 81 func (a *Arena) getBytes(offset uint32, size uint16) []byte { 82 if offset == 0 { 83 return nil 84 } 85 86 return a.buf[offset : offset+uint32(size)] 87 } 88 func (a *Arena) getListNode(offset uint32) *listNode { 89 if offset == 0 { 90 return nil 91 } 92 93 return (*listNode)(unsafe.Pointer(&a.buf[offset])) 94 } 95 96 func (a *Arena) getListNodeOffset(n *listNode) uint32 { 97 if n == nil { 98 return 0 99 } 100 101 offset := uintptr(unsafe.Pointer(n)) - uintptr(unsafe.Pointer(&a.buf[0])) 102 return uint32(offset) 103 }