backend

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package backend contains internal storage backends used by the public pool runtime.

The package is intentionally not exported because backend choice is an implementation detail of arcoris.dev/pool. Callers should reason in terms of lifecycle policy exposed by pool.Options and pool.Pool, not in terms of the concrete low-level reuse mechanism.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type SyncPool

type SyncPool[T any] struct {
	// contains filtered or unexported fields
}

SyncPool is a typed internal adapter over sync.Pool.

Purpose

The public package-level Pool[T] is responsible for lifecycle policy: creation, reset, reuse admission, and explicit drop handling. None of that policy belongs in the low-level storage backend. This type exists to isolate the backend-specific details of storing and retrieving reusable values via sync.Pool while keeping the public runtime small and policy-oriented.

In practice, SyncPool is the boundary that converts an untyped any-based backend into a typed generic backend suitable for the rest of the package. It centralizes the only place where values cross the boundary between the generic public API and the underlying sync.Pool API.

Why this type exists instead of using sync.Pool directly everywhere

  • It keeps all sync.Pool-specific mechanics in one internal location.
  • It prevents the public pool runtime from repeating any <-> T conversion logic.
  • It makes future backend replacement or debug instrumentation local.
  • It keeps package-level architecture explicit: policy above, storage backend below.

Contract

  • SyncPool does not implement reset, validation, admission, or drop policy. Those decisions are made by the public Pool[T].
  • SyncPool only stores and retrieves values of type T.
  • NewSyncPool requires a non-nil constructor.
  • The zero value of SyncPool is not ready for use.
  • SyncPool values must not be copied after first use because the type owns an embedded sync.Pool.

Concurrency

SyncPool is safe for concurrent use because it delegates storage and reuse mechanics to sync.Pool, which is itself designed for concurrent access.

Performance notes

The adapter intentionally stays minimal:

  • no extra indirection beyond the typed wrapper itself;
  • no runtime hook dispatch inside Get/Put;
  • no statistics or ownership tracking in the hot path;
  • only one typed assertion site on Get.

For the intended use of arcoris.dev/pool, this keeps the backend thin enough to remain an implementation detail rather than becoming a second runtime layer.

T is typically expected to be a pointer-like reusable value, such as *ParserState or *RequestContext, but the adapter itself is generic and does not impose that restriction.

Internal invariant

Every value stored in the underlying sync.Pool must have dynamic type T. Any violation of that invariant indicates an internal programming error in this repository, not a recoverable user-space condition.

The type is deliberately small and stable. If the project later adds debug instrumentation, alternate backends, or build-tag-specific behaviour, those changes should continue to preserve this file as the narrow typed bridge over sync.Pool.

func NewSyncPool

func NewSyncPool[T any](newFn func() T) *SyncPool[T]

NewSyncPool constructs a typed sync.Pool-backed backend.

newFn is mandatory. It is used as the slow-path constructor whenever the underlying sync.Pool cannot provide a reusable value.

NewSyncPool panics if newFn is nil. Although higher layers already validate this condition when resolving public Options, the backend defends its own contract explicitly so that it remains correct and self-contained when read or tested in isolation.

The constructor installed into sync.Pool.New must return values whose dynamic type is exactly T. That invariant is required for Get to remain type-safe.

func (*SyncPool[T]) Get

func (p *SyncPool[T]) Get() T

Get returns a reusable value of type T from the backend.

Behaviour

  • If sync.Pool has a previously stored value, that value is returned.
  • Otherwise sync.Pool invokes the constructor installed by NewSyncPool.
  • The result is asserted back to T and returned to the caller.

This method performs no lifecycle work beyond retrieval. In particular, Get does not reset the value, validate it, or decide whether it should have been retained. Those responsibilities belong to the public pool runtime.

Panics

Get panics if the backend returns a value whose dynamic type is not T. Such a panic represents an internal invariant violation: something in the package stored the wrong value into the backend. This is intentionally treated as a hard failure rather than a recoverable error because continuing after type corruption would make the runtime semantics unsound.

func (*SyncPool[T]) Put

func (p *SyncPool[T]) Put(value T)

Put stores a value for future reuse.

Put intentionally performs no reset or policy checks. The caller is expected to have already decided that the value is eligible for reuse and to have brought it into a clean state.

In other words, Put is the final low-level storage step of the return path, not the place where lifecycle policy is enforced.

Put panics on a nil receiver because using an uninitialized backend is an internal programming error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL