github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/cache/lrucache/entry_normal.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 //go:build (!invariants && !tracing) || race 16 // +build !invariants,!tracing race 17 18 package lrucache 19 20 import ( 21 "runtime" 22 "sync" 23 "unsafe" 24 25 "github.com/zuoyebang/bitalosdb/internal/invariants" 26 "github.com/zuoyebang/bitalosdb/internal/manual" 27 ) 28 29 const ( 30 entrySize = int(unsafe.Sizeof(entry{})) 31 entryAllocCacheLimit = 128 32 entriesGoAllocated = invariants.RaceEnabled || !cgoEnabled 33 ) 34 35 var entryAllocPool = sync.Pool{ 36 New: func() interface{} { 37 return newEntryAllocCache() 38 }, 39 } 40 41 func entryAllocNew() *entry { 42 a := entryAllocPool.Get().(*entryAllocCache) 43 e := a.alloc() 44 entryAllocPool.Put(a) 45 return e 46 } 47 48 func entryAllocFree(e *entry) { 49 a := entryAllocPool.Get().(*entryAllocCache) 50 a.free(e) 51 entryAllocPool.Put(a) 52 } 53 54 type entryAllocCache struct { 55 entries []*entry 56 } 57 58 func newEntryAllocCache() *entryAllocCache { 59 c := &entryAllocCache{} 60 if !entriesGoAllocated { 61 runtime.SetFinalizer(c, freeEntryAllocCache) 62 } 63 return c 64 } 65 66 func freeEntryAllocCache(obj interface{}) { 67 c := obj.(*entryAllocCache) 68 for i, e := range c.entries { 69 c.dealloc(e) 70 c.entries[i] = nil 71 } 72 } 73 74 func (c *entryAllocCache) alloc() *entry { 75 n := len(c.entries) 76 if n == 0 { 77 if entriesGoAllocated { 78 return &entry{} 79 } 80 b := manual.New(entrySize) 81 return (*entry)(unsafe.Pointer(&b[0])) 82 } 83 e := c.entries[n-1] 84 c.entries = c.entries[:n-1] 85 return e 86 } 87 88 func (c *entryAllocCache) dealloc(e *entry) { 89 if !entriesGoAllocated { 90 buf := (*[manual.MaxArrayLen]byte)(unsafe.Pointer(e))[:entrySize:entrySize] 91 manual.Free(buf) 92 } 93 } 94 95 func (c *entryAllocCache) free(e *entry) { 96 if len(c.entries) == entryAllocCacheLimit { 97 c.dealloc(e) 98 return 99 } 100 c.entries = append(c.entries, e) 101 }