mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 03:07:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			104 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use
 | 
						|
// of this source code is governed by a BSD-style license that can be found in
 | 
						|
// the LICENSE file.
 | 
						|
//
 | 
						|
//go:build (!invariants && !tracing) || race
 | 
						|
// +build !invariants,!tracing race
 | 
						|
 | 
						|
package cache
 | 
						|
 | 
						|
import (
 | 
						|
	"runtime"
 | 
						|
	"sync"
 | 
						|
	"unsafe"
 | 
						|
 | 
						|
	"github.com/cockroachdb/pebble/internal/invariants"
 | 
						|
	"github.com/cockroachdb/pebble/internal/manual"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	entrySize            = int(unsafe.Sizeof(entry{}))
 | 
						|
	entryAllocCacheLimit = 128
 | 
						|
	// Avoid using runtime.SetFinalizer in race builds as finalizers tickle a bug
 | 
						|
	// in the Go race detector in go1.15 and earlier versions. This requires that
 | 
						|
	// entries are Go allocated rather than manually allocated.
 | 
						|
	//
 | 
						|
	// If cgo is disabled we need to allocate the entries using the Go allocator
 | 
						|
	// and is violates the Go GC rules to put Go pointers (such as the entry
 | 
						|
	// pointer fields) into untyped memory (i.e. a []byte).
 | 
						|
	entriesGoAllocated = invariants.RaceEnabled || !cgoEnabled
 | 
						|
)
 | 
						|
 | 
						|
var entryAllocPool = sync.Pool{
 | 
						|
	New: func() interface{} {
 | 
						|
		return newEntryAllocCache()
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
func entryAllocNew() *entry {
 | 
						|
	a := entryAllocPool.Get().(*entryAllocCache)
 | 
						|
	e := a.alloc()
 | 
						|
	entryAllocPool.Put(a)
 | 
						|
	return e
 | 
						|
}
 | 
						|
 | 
						|
func entryAllocFree(e *entry) {
 | 
						|
	a := entryAllocPool.Get().(*entryAllocCache)
 | 
						|
	a.free(e)
 | 
						|
	entryAllocPool.Put(a)
 | 
						|
}
 | 
						|
 | 
						|
type entryAllocCache struct {
 | 
						|
	entries []*entry
 | 
						|
}
 | 
						|
 | 
						|
func newEntryAllocCache() *entryAllocCache {
 | 
						|
	c := &entryAllocCache{}
 | 
						|
	if !entriesGoAllocated {
 | 
						|
		// Note the use of a "real" finalizer here (as opposed to a build tag-gated
 | 
						|
		// no-op finalizer). Without the finalizer, objects released from the pool
 | 
						|
		// and subsequently GC'd by the Go runtime would fail to have their manually
 | 
						|
		// allocated memory freed, which results in a memory leak.
 | 
						|
		// lint:ignore SetFinalizer
 | 
						|
		runtime.SetFinalizer(c, freeEntryAllocCache)
 | 
						|
	}
 | 
						|
	return c
 | 
						|
}
 | 
						|
 | 
						|
func freeEntryAllocCache(obj interface{}) {
 | 
						|
	c := obj.(*entryAllocCache)
 | 
						|
	for i, e := range c.entries {
 | 
						|
		c.dealloc(e)
 | 
						|
		c.entries[i] = nil
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c *entryAllocCache) alloc() *entry {
 | 
						|
	n := len(c.entries)
 | 
						|
	if n == 0 {
 | 
						|
		if entriesGoAllocated {
 | 
						|
			return &entry{}
 | 
						|
		}
 | 
						|
		b := manual.New(entrySize)
 | 
						|
		return (*entry)(unsafe.Pointer(&b[0]))
 | 
						|
	}
 | 
						|
	e := c.entries[n-1]
 | 
						|
	c.entries = c.entries[:n-1]
 | 
						|
	return e
 | 
						|
}
 | 
						|
 | 
						|
func (c *entryAllocCache) dealloc(e *entry) {
 | 
						|
	if !entriesGoAllocated {
 | 
						|
		buf := (*[manual.MaxArrayLen]byte)(unsafe.Pointer(e))[:entrySize:entrySize]
 | 
						|
		manual.Free(buf)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c *entryAllocCache) free(e *entry) {
 | 
						|
	if len(c.entries) == entryAllocCacheLimit {
 | 
						|
		c.dealloc(e)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	c.entries = append(c.entries, e)
 | 
						|
}
 |