github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/arenaskl/arena.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package arenaskl 16 17 import ( 18 "errors" 19 "math" 20 "sync/atomic" 21 "unsafe" 22 ) 23 24 type Arena struct { 25 n uint64 26 buf []byte 27 } 28 29 const ( 30 align4 = 3 31 ) 32 33 var ( 34 ErrArenaFull = errors.New("allocation failed because arena is full") 35 ) 36 37 func NewArena(buf []byte) *Arena { 38 return &Arena{ 39 n: 1, 40 buf: buf, 41 } 42 } 43 44 func (a *Arena) Size() uint32 { 45 s := atomic.LoadUint64(&a.n) 46 if s > math.MaxUint32 { 47 return math.MaxUint32 48 } 49 return uint32(s) 50 } 51 52 func (a *Arena) Capacity() uint32 { 53 return uint32(len(a.buf)) 54 } 55 56 func (a *Arena) alloc(size, align, overflow uint32) (uint32, uint32, error) { 57 origSize := atomic.LoadUint64(&a.n) 58 if int(origSize) > len(a.buf) { 59 return 0, 0, ErrArenaFull 60 } 61 62 padded := size + align 63 64 newSize := atomic.AddUint64(&a.n, uint64(padded)) 65 if int(newSize)+int(overflow) > len(a.buf) { 66 return 0, 0, ErrArenaFull 67 } 68 69 offset := (uint32(newSize) - padded + align) & ^align 70 return offset, padded, nil 71 } 72 73 func (a *Arena) getBytes(offset uint32, size uint32) []byte { 74 if offset == 0 { 75 return nil 76 } 77 return a.buf[offset : offset+size : offset+size] 78 } 79 80 func (a *Arena) getPointer(offset uint32) unsafe.Pointer { 81 if offset == 0 { 82 return nil 83 } 84 return unsafe.Pointer(&a.buf[offset]) 85 } 86 87 func (a *Arena) getPointerOffset(ptr unsafe.Pointer) uint32 { 88 if ptr == nil { 89 return 0 90 } 91 return uint32(uintptr(ptr) - uintptr(unsafe.Pointer(&a.buf[0]))) 92 }