Documentation
¶
Overview ¶
Package poolswap provides a goroutine-safe container for hot-swapping heavy objects (e.g. caches or configs) without blocking readers or generating GC pressure.
This works by wrapping a sync.Pool with atomic reference counting. This allows readers to safely hold references to an object while a writer swaps it out. Old objects are automatically returned to the pool once all readers are done.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Container ¶
Container manages a "current" active pointer.
func NewContainer ¶
NewContainer creates a container for objects from the given Pool, initialized with the init object.
The object must be not be owned by another instance of poolswap.Container; The container takes ownership of the given initial value (reference count set to 1).
func NewEmptyContainer ¶
NewEmptyContainer creates a container for objects from the given Pool. The container starts empty (current is nil) until Update is called.
func (*Container[T, PT]) Acquire ¶
func (c *Container[T, PT]) Acquire() *T
Acquire returns the current active object with its reference count incremented. The caller owns this reference and must call Release() when finished.
Returns nil if the container is empty.
func (*Container[T, PT]) GetNew ¶
func (c *Container[T, PT]) GetNew() *T
GetNew is a convenience proxy to the underlying Pool's Get.
func (*Container[T, PT]) Release ¶
func (c *Container[T, PT]) Release(obj *T)
Release is a convenience proxy to the underlying Pool's Release.
func (*Container[T, PT]) Update ¶
func (c *Container[T, PT]) Update(newObj *T)
Update the container to point at a new object.
It sets the new object as current and releases the old object. The old object will be returned to the pool once all existing readers release it.
func (*Container[T, PT]) WithAcquire ¶
func (c *Container[T, PT]) WithAcquire(fn func(obj *T))
WithAcquire is a helper that executes fn with the current object (can be nil) and automatically releases it afterwards.
type Pool ¶
type Pool[T any, PT PtrRef[T]] struct { // Reset is called when refs hit 0. // It should clear the object's state (e.g. clear maps, reset slices). // Return true to put it back in the pool, false to discard (GC). Reset func(*T) bool // contains filtered or unexported fields }
Pool wraps a sync.Pool with reference counting.
When an object's reference count hits zero, the Pool cleans it via the Reset function and returns it to the internal sync.Pool.
T is the struct type (e.g., MyCache). PT is the pointer type (e.g., *MyCache).
func NewPool ¶
NewPool creates a pool for type T. factory allocates a new, empty T. resetter prepares a used T for reuse (or returns false to discard it).
type PtrRef ¶
type PtrRef[T any] interface { *T Referenceable }
PtrRef is a pointer type that is Referenceable (embeds Ref or RefNoPadding).
type Ref ¶
type Ref struct {
// contains filtered or unexported fields
}
Ref should be embedded as the first field in structs you want to use with this library. Includes cache-line padding to prevent false sharing on the counter.
func (*Ref) DebugPeekRef ¶
DebugPeekRef returns the current reference count; for testing and debugging only.
type RefNoPadding ¶ added in v0.1.2
type RefNoPadding struct {
// contains filtered or unexported fields
}
RefNoPadding is the same as Ref, but without the padding.
func (*RefNoPadding) DebugPeekRef ¶ added in v0.1.2
func (r *RefNoPadding) DebugPeekRef() int64
DebugPeekRef returns the current reference count; for testing and debugging only.
type Referenceable ¶
type Referenceable interface {
// contains filtered or unexported methods
}
Referenceable defines the contract for objects managed by this library. The only way to implement this is to embed our Ref (or RefNoPadding) struct.