snapshot

package
v0.1.21 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 2 Imported by: 0

README

snapshot

Copy-on-write container primitive for the SDK kernel. Stdlib-only.

import (
	"maps"

	"github.com/kitsunium/sdk/internal/kernel/snapshot"
)

// Read-mostly shared state: lock-free Load, mutex-serialised writers.
var routes snapshot.Value[map[string]int]

// Publish a new snapshot under the writer lock (copy-on-write).
routes.Update(func(cur *map[string]int) *map[string]int {
	next := map[string]int{}
	if cur != nil {
		maps.Copy(next, *cur)
	}
	next["/health"] = 200
	return &next
})

// Read without locking — one atomic load, zero allocation.
if m := routes.Load(); m != nil {
	_ = (*m)["/health"]
}

Value[T] holds a *T behind an atomic.Pointer[T]: Load is lock-free and allocation-free, while Store / Swap / Update serialise on a mutex so a read-modify-write publish is race-free. The codec registry (internal/core/codec) is built on it — three atomic.Pointer[map] fields with hand-rolled CAS loops collapse to three Value[map] fields.

See ADR 0011 for the design rationale and the layering contract.

Documentation

Overview

Package snapshot provides Value[T any], a copy-on-write container for read-mostly shared state. Load is lock-free and allocation-free (a single atomic.Pointer load); writers (Store / Swap / Update) serialise on a mutex so a read-modify-write publish never loses a concurrent update. Stdlib-only and domain-neutral: any frozen-after-init or rarely-mutated table — a codec registry, a routing table, a feature-flag map, a hot-reloaded config — can reuse it.

The codec registry (internal/core/codec) is built ON this primitive: three atomic.Pointer[map] fields with hand-rolled CAS-loop writers collapse to three Value[map] fields. The mechanism lives here; the domain clone logic stays with the consumer (ADR 0011).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Value

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

Value is a copy-on-write container for a *T. Readers call Load with no lock; writers replace the whole pointer under a mutex so concurrent read-modify-write publishes cannot lose updates. The zero value is ready to use — Load returns nil until the first Store. Always used behind a pointer: the embedded mutex and atomic.Pointer must not be copied.

func NewValue

func NewValue[T any](initial *T) *Value[T]

NewValue returns a Value holding initial. A nil initial is valid and leaves the container empty (Load returns nil), the same state as the zero value — offered as call-site sugar when an initial value is already known.

func (*Value[T]) Load

func (v *Value[T]) Load() *T

Load returns the current value pointer without taking the lock — a single atomic load, zero allocation. This is the hot path. The returned *T is shared with every other reader and MUST be treated as immutable: mutate a clone and publish it via Store or Update instead.

func (*Value[T]) Store

func (v *Value[T]) Store(next *T)

Store atomically replaces the current value with next. It takes the writer lock so a Store cannot interleave with an in-flight Update's read-modify-write and clobber it.

func (*Value[T]) Swap

func (v *Value[T]) Swap(next *T) *T

Swap atomically replaces the current value with next and returns the previous value pointer (nil when the container was empty). Takes the writer lock for the same reason as Store.

func (*Value[T]) Update

func (v *Value[T]) Update(fn func(current *T) (next *T))

Update runs fn under the writer lock and publishes its result. fn receives the current value (nil when empty) and returns the replacement; it MUST NOT mutate the value it is handed — other goroutines may be reading it — and should build and return a fresh *T. fn MUST NOT call Store / Swap / Update on the same Value, which would deadlock. Returning the unchanged current pointer is a no-op publish, which lets fn abort a conditional update.

Jump to

Keyboard shortcuts

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