adt

package
v0.14.1 Latest Latest
Warning

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

Go to latest
Published: Jan 14, 2026 License: Apache-2.0 Imports: 14 Imported by: 18

Documentation

Overview

Package adt provides "atomic data types" as strongly-typed generic helpers for simple atomic operations (including sync.Map, sync.Pool, and a typed value).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompareAndSwap

func CompareAndSwap[T comparable, A AtomicValue[T]](a A, oldVal, newVal T) bool

CompareAndSwap exposes the CompareAndSwap option for atomics that store values of comparable types. Only supports the Atomic and Synchronized types, as well as any type that implement a CompareAndSwap method for old/new values of T. Panics for all other types.

func Lock added in v0.10.0

func Lock(mtx *sync.Mutex) *sync.Mutex

Lock takes the lock, locks it, and then returns it.

This, in combination With() makes it possible to have a single statement for managing a mutex in a defer, given the evaluation time of defer arguments, as in:

mtx := &sync.Mutex{}
defer adt.With(adt.Lock(mtx))

func LockR added in v0.12.0

func LockR(m *sync.RWMutex) *sync.RWMutex

LockR takes an RWMutex locks it in read-mode and returns it to be unlocked WithR.

func LockW added in v0.12.0

func LockW(m *sync.RWMutex) *sync.RWMutex

LockW takes a RWMutex, locks as a write, and returns it to be unlocked by WithW.

func Reset added in v0.10.2

func Reset[T stw.Integers, A AtomicValue[T]](a A) T

Reset sets the atomic, for an atomic value that holds a number, to 0, and returns the previously stored value.

func SafeSet

func SafeSet[T comparable, A AtomicValue[T]](atom A, value T)

SafeSet sets the atomic to the given value only if the value is not the Zero value for that type.

func With added in v0.10.0

func With(mtx *sync.Mutex)

With takes a lock as an argument and then releases the lock when it executes.

This, in combination with Lock makes it possible to have a single statement for managing a mutex in a defer, given the evaluation time of defer arguments, as in:

mtx := &sync.Mutex{}
defer adt.With(adt.Lock(mtx))

func WithR added in v0.12.0

func WithR(m *sync.RWMutex)

WithR takes a lock that's been locked in read mood, as an argument and then releases the lock when it executes.

func WithW added in v0.12.0

func WithW(m *sync.RWMutex)

WithW takes a write locked RWMutex as an argument and then releases when the function it executes.

Types

type Atomic

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

Atomic is a very simple atomic Get/Set operation, providing a generic type-safe implementation wrapping sync/atomic.Value. The primary caveat is that interface types are not compatible with adt.Atomic as a result of the standard library's underlying atomic type. To store interface objects atomically you can wrap the object in a function, using ft.Wrapper.

func NewAtomic

func NewAtomic[T any](initial T) *Atomic[T]

NewAtomic creates a new Atomic Get/Set value with the initial value already set. This is a helper for creating a new atomic with a default value set.

func (*Atomic[T]) Get

func (a *Atomic[T]) Get() T

Get resolves the atomic value, returning the zero value of the type T if the value is unset.

func (*Atomic[T]) Load added in v0.10.2

func (a *Atomic[T]) Load() T

Load returns the value stored in the atomic. It mirrors the standard library's interface for atomics.

func (*Atomic[T]) Set

func (a *Atomic[T]) Set(in T)

Set atomically sets the value of the Atomic.

func (*Atomic[T]) Store added in v0.10.2

func (a *Atomic[T]) Store(in T)

Store saves the value in the atomic.

func (*Atomic[T]) Swap

func (a *Atomic[T]) Swap(newVal T) (old T)

Swap does an in place exchange of the contents of a value exchanging the new value for the old. Unlike sync.Atomic.Swap() if new is nil, adt.Atomic.Swap() does NOT panic, and instead constructs the zero value of type T.

type AtomicFloat64 added in v0.14.0

type AtomicFloat64 struct {
	// contains filtered or unexported fields
}

AtomicFloat64 provides full-fidelity atomic storage for float64 values (by converting them) as bits to int64 and storing them using sync/atomic.Int64 values. The Add() method is correct, but must spin, unlike for integers which rely on an optimized underlying instruction.

AtomicFloat64 shares an interface with the adt.Atomic wrapper types.

func (*AtomicFloat64) Add added in v0.14.0

func (a *AtomicFloat64) Add(delta float64) float64

Add atomically increments the current float64 value by delta and returns the new value. This method uses a compare-and-swap loop since there is no atomic float64 increment instruction.

func (*AtomicFloat64) CompareAndSwap added in v0.14.0

func (a *AtomicFloat64) CompareAndSwap(oldVal, newVal float64) bool

CompareAndSwap atomically examines the current value against oldVal and, if they are equal, replaces it with newVal. It returns true if the replacement was performed.

func (*AtomicFloat64) Get added in v0.14.0

func (a *AtomicFloat64) Get() float64

Get retrieves the current float64 value from the atomic variable. This is an alias for Load() for consistency with other atomic interfaces.

func (*AtomicFloat64) Load added in v0.14.0

func (a *AtomicFloat64) Load() float64

Load atomically retrieves and returns the current float64 value.

func (*AtomicFloat64) Set added in v0.14.0

func (a *AtomicFloat64) Set(in float64)

Set writes a new float64 value to the atomic variable. This is an alias for Store() for consistency with other atomic interfaces.

func (*AtomicFloat64) Store added in v0.14.0

func (a *AtomicFloat64) Store(val float64)

Store atomically writes the given float64 value.

func (*AtomicFloat64) Swap added in v0.14.0

func (a *AtomicFloat64) Swap(newVal float64) float64

Swap atomically replaces the current value with newVal and returns the previous float64 value.

type AtomicInteger added in v0.14.0

type AtomicInteger[T stw.Integers] struct {
	// contains filtered or unexported fields
}

AtomicInteger is a wrapper around sync/atomic.Int64 that provides type-preserving atomic storage for all numeric types.

AtomicInteger shares an interface with the adt.AtomicInteger wrapper types.

func (*AtomicInteger[T]) Add added in v0.14.0

func (a *AtomicInteger[T]) Add(delta T) T

Add atomically increments the current value by delta and returns the new value.

func (*AtomicInteger[T]) CompareAndSwap added in v0.14.0

func (a *AtomicInteger[T]) CompareAndSwap(oldVal, newValue T) bool

CompareAndSwap atomically examines the current value against oldVal and, if they are equal, replaces it with newValue. It returns true if the replacement was performed.

func (*AtomicInteger[T]) Get added in v0.14.0

func (a *AtomicInteger[T]) Get() T

Get retrieves the current value stored in the atomic variable. This is an alias for Load() for consistency with other atomic interfaces.

func (*AtomicInteger[T]) Load added in v0.14.0

func (a *AtomicInteger[T]) Load() T

Load atomically retrieves and returns the current value.

func (*AtomicInteger[T]) Set added in v0.14.0

func (a *AtomicInteger[T]) Set(in T)

Set writes a new value to the atomic variable. This is an alias for Store() for consistency with other atomic interfaces.

func (*AtomicInteger[T]) Store added in v0.14.0

func (a *AtomicInteger[T]) Store(in T)

Store atomically writes the given value.

func (*AtomicInteger[T]) Swap added in v0.14.0

func (a *AtomicInteger[T]) Swap(newVal T) T

Swap atomically replaces the current value with newVal and returns the previous value.

type AtomicValue added in v0.9.0

type AtomicValue[T any] interface {
	Load() T
	Store(T)
	Swap(T) T
}

AtomicValue describes the public interface of the Atomic type. Use this definition to compose atomic types into other interfaces.

type Map

type Map[K comparable, V any] struct {
	// Default handles construction and pools objects in
	// the map for the Ensure and Get operations which must
	// construct zero-value items. No configuration or
	// construction is necessary; however, callers can modify the
	// default value constructed as needed.
	Default Pool[V]
	// contains filtered or unexported fields
}

Map provides a wrapper around the standard library's sync.Map type with key/value types enforced by generics. Additional helpers support adding multiple items to the map, while the iteration methods, and Extend provide compatibility with iter.Seq2[] sequences.

func (*Map[K, V]) Check added in v0.10.0

func (mp *Map[K, V]) Check(key K) (ok bool)

Check returns true if the key exists in the map or false otherwise.

func (*Map[K, V]) Delete

func (mp *Map[K, V]) Delete(key K)

Delete removes a key--and its corresponding value--from the map, if it exists.

func (*Map[K, V]) Ensure

func (mp *Map[K, V]) Ensure(key K) bool

Ensure is similar to EnsureStore but provides the default value as a function that produces a value rather than the value directly. The returned value is *always* the value of the key, which is either the value from the map or the value produced by the function.

The constructor function is *always* called, even when the key exists in the map. Unlike Get and Ensure which have similar semantics and roles, the value produced by function does not participate in the default object pool.

func (*Map[K, V]) Extend

func (mp *Map[K, V]) Extend(seq iter.Seq2[K, V])

Extend adds values from the input sequence to the current map. If keys in the input sequence exist in the map already, they're overridden. There is no isolation. While the operation is entirely thread safe (or at least as safe as the input iterator is), adding individual key/value pairs to the map may interleave with other operations.

func (*Map[K, V]) Get

func (mp *Map[K, V]) Get(key K) (out V)

Get returns the value from the map. If the key is not present in the map, this returns the zero value for V.

func (*Map[K, V]) Iterator

func (mp *Map[K, V]) Iterator() iter.Seq2[K, V]

Iterator returns a native go iterator for a Map object.

func (*Map[K, V]) Keys added in v0.8.5

func (mp *Map[K, V]) Keys() iter.Seq[K]

Keys returns an iterator that yields all of the keys in the map.

This operation relies on a the underlying Map's Range method, and advances lazily through the Range operation as callers advance the iterator. Be aware that this produces a iterator that does not reflect any particular point-in-time view of the underlying map.

func (*Map[K, V]) Len

func (mp *Map[K, V]) Len() (count int)

Len counts and reports on the number of items in the map. This is provided by iterating and counting the values in the map, and has O(n) performance.

Len uses a range function and therefore does not reflect a specific snapshot of the map at any time if keys are being deleted while Len is running. Len will never report a number that is larger than the total number of items in the map while Len is running, but the number of items in the map may be smaller at the beginning and/or the end than reported.

func (*Map[K, V]) Load

func (mp *Map[K, V]) Load(key K) (V, bool)

Load retrieves the value from the map. The semantics are the same as for maps in go: if the value does not exist it always returns the zero value for the type, while the second value indicates if the key was present in the map.

func (*Map[K, V]) MarshalJSON

func (mp *Map[K, V]) MarshalJSON() ([]byte, error)

MarshalJSON produces a JSON form of the map, using a Range function to iterate through the values in the map. Range functions do not reflect a specific snapshot of the map if the map is being modified while being marshaled: keys will only appear at most once but order or which version of a value is not defined.

func (*Map[K, V]) Set

func (mp *Map[K, V]) Set(key K, value V) (ok bool)

Set adds the value to the map, overriding any existing value. The return reports if the key existed in the map before the operation.

func (*Map[K, V]) Store

func (mp *Map[K, V]) Store(k K, v V)

Store adds a key and value to the map, replacing any existing values as needed.

func (*Map[K, V]) UnmarshalJSON

func (mp *Map[K, V]) UnmarshalJSON(in []byte) error

UnmarshalJSON takes a json sequence and adds the values to the map. This does not remove or reset the values in the map, and other operations may interleave during this operation.

func (*Map[K, V]) Values added in v0.8.5

func (mp *Map[K, V]) Values() iter.Seq[V]

Values returns an iterator that yields all of the values in the map.

This operation relies on a the underlying Map's Range iterator, and advances lazily through the Range operation as callers advance the iterator. Be aware that this produces an iterator that does not reflect any particular point-in-time view of the underlying map.

type Once added in v0.9.0

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

Once provides a mnemonic form of sync.Once, caching and returning a value after the Do() function is called.

Panics are only thrown when the underlying constructor is called (and it panics.) Nil constructors are ignored and subsequent attempts to access the value will return the zero value for the return type.

func NewOnce added in v0.10.0

func NewOnce[T any](fn func() T) *Once[T]

NewOnce creates a Once object and initializes it with the function provided. This is optional and this function can be later overridden by Set() or Do(). When the operation is complete, the Once value is populated and the .Resolve() method will return the value.

func (*Once[T]) Called added in v0.10.0

func (o *Once[T]) Called() bool

Called returns true if the Once object has been called or is currently running, and false otherwise.

func (*Once[T]) Defined added in v0.10.0

func (o *Once[T]) Defined() bool

Defined returns true when the function has been set. Use only for observational purpsoses. Though the value is stored in an atomic, it does reflect the state of the underlying operation.

func (*Once[T]) Do added in v0.9.0

func (o *Once[T]) Do(ctor func() T) T

Do runs the function provided, and caches the results. All subsequent calls to Do or Resolve() are noops. If multiple callers use Do/Resolve at the same time, like sync.Once.Do none will return until return until the first operation completes.

Functions passed to Do should return values that are safe for concurrent access: while the Do/Resolve operations are synchronized, the return value from Do is responsible for its own synchronization.

func (*Once[T]) Resolve added in v0.10.0

func (o *Once[T]) Resolve() T

Resolve runs the stored, if and only if it hasn't been run function and returns its output. If the constructor hasn't been populated, as with Set(), then Resolve() will return the zero value for T. Once the function has run, Resolve will continue to return the cached value.

func (*Once[T]) Set added in v0.10.0

func (o *Once[T]) Set(constr func() T)

Set sets the constrctor/operation for the Once object, but does not execute the operation. The operation is atomic, is a noop after the operation has completed, will not reset the operation or the cached value.

type OrderedMap added in v0.14.0

type OrderedMap[K comparable, V any] = dt.OrderedMap[K, V]

OrderedMap is an alias of the `dt` package's ordered map implementation, which is (incidentally as an implementation detail) safe for concurrent use.

type OrderedSet added in v0.14.0

type OrderedSet[T comparable] struct {
	// contains filtered or unexported fields
}

OrderedSet provides a thread-safe generic set implementation that always maintains insertion order. All operations are synchronized.

func MakeOrderedSet added in v0.14.0

func MakeOrderedSet[T comparable](seq iter.Seq[T]) *OrderedSet[T]

MakeOrderedSet constructs an ordered set and adds all items from the input sequence in order.

func (*OrderedSet[T]) Add added in v0.14.0

func (s *OrderedSet[T]) Add(in T) (ok bool)

Add adds an item to the set and returns true if the item had been in the set before Add. In all cases when Add returns, the item is a member of the set.

func (*OrderedSet[T]) Check added in v0.14.0

func (s *OrderedSet[T]) Check(in T) bool

Check returns true if the item is in the set.

func (*OrderedSet[T]) Delete added in v0.14.0

func (s *OrderedSet[T]) Delete(in T) bool

Delete removes the item from the set, returning true when the item existed in the Set and false otherwise.

func (*OrderedSet[T]) Extend added in v0.14.0

func (s *OrderedSet[T]) Extend(iter iter.Seq[T])

Extend adds all items encountered in the iterator to the set.

func (*OrderedSet[T]) Iterator added in v0.14.0

func (s *OrderedSet[T]) Iterator() iter.Seq[T]

Iterator returns a new-style native Go iterator for the items in the set in insertion order.

func (*OrderedSet[T]) Len added in v0.14.0

func (s *OrderedSet[T]) Len() int

Len returns the number of items tracked in the set.

func (*OrderedSet[T]) MarshalJSON added in v0.14.0

func (s *OrderedSet[T]) MarshalJSON() ([]byte, error)

MarshalJSON generates a JSON array of the items in the set in insertion order.

func (*OrderedSet[T]) SortMerge added in v0.14.0

func (s *OrderedSet[T]) SortMerge(cf func(T, T) int)

SortMerge sorts the elements in the set using a merge sort algorithm.

func (*OrderedSet[T]) SortQuick added in v0.14.0

func (s *OrderedSet[T]) SortQuick(cf func(T, T) int)

SortQuick sorts the elements in the set using a stable sort. Typically faster than SortMerge, but potentially more memory intensive for some types.

func (*OrderedSet[T]) UnmarshalJSON added in v0.14.0

func (s *OrderedSet[T]) UnmarshalJSON(in []byte) error

UnmarshalJSON reads input JSON data, constructs an array in memory and then adds items from the array to existing set. Items that are in the set when UnmarshalJSON begins are not modified.

type Pool

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

Pool is an ergonomic wrapper around sync.Pool that provides some additional functionality: generic type interface, a default clean up hook to modify (optionally) the object before returning it to the pool.

Additionally, the Make() method attaches an object finalizer to the object produced by the pool that returns the object to the pool rather than garbage collect it. This is likely to be less efficient than return the objects to the pool using defer functions, but may be more ergonomic in some situations.

Pool can be used with default construction; however, you should set the Constructor before calling Get() or Make() on the pool.

func DefaultBufferPool added in v0.10.4

func DefaultBufferPool() *Pool[stw.Slice[byte]]

DefaultBufferPool creates a pool of byte slices with a maximum size of 64kb. All other slices are discarded. These are the same settings as used by the fmt package's buffer pool.

The type of the pooled object is stw.Slice[byte], a simple type alias for Go's slice type with convenience methods for common slice operations. You can use these values interchangeably with vanilla byte slices, as you need and wish.

func MakeBufferPool added in v0.10.4

func MakeBufferPool(minVal, maxVal int) *Pool[stw.Slice[byte]]

MakeBufferPool constructs a pool of byte slices. New slices are allocated with the specified minimum capacity, and are always resliced to be 0 length before reentering the pool. Slices that are larger than the specified maximum do not reenter the pool.

Min/Max values less than 0 are ignored, and the highest value is always used as the max the lowest as the min, regardless of position. MakeBufferPool panics with an invariant violation if the max capacity value is zero.

The type of the pooled object is stw.Slice[byte], a simple type alias for Go's slice type with convenience methods for common slice operations. You can use these values interchangeably with vanilla byte slices, as you need and wish.

func MakeBytesBufferPool added in v0.10.4

func MakeBytesBufferPool(capacity int) *Pool[*bytes.Buffer]

MakeBytesBufferPool configures a pool of *bytes.Buffers. Buffers are always reset before reentering the pool, and are pre-allocated with the specified capacity. Negative initial capcity values are ignored.

func (*Pool[T]) FinalizeSetup added in v0.10.4

func (p *Pool[T]) FinalizeSetup()

FinalizeSetup prevents future calls from setting the constructor or cleanup hooks. Once a pool's setup has been finalized it cannot be unset: future attempts to set the constructor or cleanup hook result in a panic and invariant violation. FinalizeSetup is safe to cull multiple times and from different go routines.

func (*Pool[T]) Get

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

Get returns an object from the pool or constructs a default object according to the constructor.

func (*Pool[T]) Make

func (p *Pool[T]) Make() T

Make gets an object out of the sync.Pool, and attaches a finalizer that returns the item to the pool when the object would be garbage collected.

Finalizer hooks are not automatically cleared by the Put() operation, so objects retrieved with Make should not be passed manually to Put().

func (*Pool[T]) Put

func (p *Pool[T]) Put(in T)

Put returns an object in the pool, calling the cleanuphook if set. Put *always* clears the object's finalizer before calling the cleanuphook or returning it to the pool.

func (*Pool[T]) SetCleanupHook

func (p *Pool[T]) SetCleanupHook(in func(T) T)

SetCleanupHook sets a function to be called on every object renetering the pool. By default, the cleanup function is a noop, and if the input function is nil, it is not set.

func (*Pool[T]) SetConstructor

func (p *Pool[T]) SetConstructor(in func() T)

SetConstructor overrides the default constructor (which makes an object with a Zero value by default) for Get/Make operations.

type Set added in v0.14.0

type Set[T comparable] struct {
	// contains filtered or unexported fields
}

Set provides a thread-safe generic unordered set implementation. All operations are synchronized. For a set that maintains insertion order, use OrderedSet.

func MakeSet added in v0.14.0

func MakeSet[T comparable](seq iter.Seq[T]) *Set[T]

MakeSet constructs an unordered set and adds all items from the input sequence.

func (*Set[T]) Add added in v0.14.0

func (s *Set[T]) Add(in T) (ok bool)

Add adds an item to the set and returns true if the item had been in the set before Add. In all cases when Add returns, the item is a member of the set.

func (*Set[T]) Check added in v0.14.0

func (s *Set[T]) Check(in T) bool

Check returns true if the item is in the set.

func (*Set[T]) Delete added in v0.14.0

func (s *Set[T]) Delete(in T) (ok bool)

Delete removes the item from the set, returning true when the item existed in the Set and false otherwise.

func (*Set[T]) Extend added in v0.14.0

func (s *Set[T]) Extend(iter iter.Seq[T])

Extend adds all items from the iterator to the set.

func (*Set[T]) Iterator added in v0.14.0

func (s *Set[T]) Iterator() iter.Seq[T]

Iterator returns a new-style native Go iterator for the items in the set. The iteration order is undefined and may vary between calls.

When Synchronized, the lock is NOT held when the iterator is advanced.

func (*Set[T]) Len added in v0.14.0

func (s *Set[T]) Len() int

Len returns the number of items tracked in the set.

func (*Set[T]) MarshalJSON added in v0.14.0

func (s *Set[T]) MarshalJSON() ([]byte, error)

MarshalJSON generates a JSON array of the items in the set. The order of items in the array is undefined.

func (*Set[T]) UnmarshalJSON added in v0.14.0

func (s *Set[T]) UnmarshalJSON(in []byte) error

UnmarshalJSON reads input JSON data, constructs an array in memory and then adds items from the array to existing set. Items that are in the set when UnmarshalJSON begins are not modified.

type Synchronized added in v0.8.7

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

Synchronized wraps an arbitrary type with a lock, and provides a functional interface for interacting with that type. In general Synchronize is ideal for container and interface types which are not safe for concurrent use, when either `adt.Map`, `adt.Atomic` are not appropriate.

func NewSynchronized added in v0.8.7

func NewSynchronized[T any](in T) *Synchronized[T]

NewSynchronized constructs a new synchronized object that wraps the input type.

func (*Synchronized[T]) Get added in v0.8.9

func (s *Synchronized[T]) Get() T

Get returns the underlying protected object.

func (*Synchronized[T]) Load added in v0.10.2

func (s *Synchronized[T]) Load() T

Load returns the underlyting protected object.

func (*Synchronized[T]) Set added in v0.8.7

func (s *Synchronized[T]) Set(in T)

Set overrides the current value of the protected object.

func (*Synchronized[T]) Store added in v0.10.2

func (s *Synchronized[T]) Store(in T)

Store replaces the value of the protected with the new provided value.

func (*Synchronized[T]) String added in v0.8.9

func (s *Synchronized[T]) String() string

String implements fmt.Stringer using this type.

func (*Synchronized[T]) Swap added in v0.8.9

func (s *Synchronized[T]) Swap(newVal T) (old T)

Swap sets the locked value to the new value and returns the old.

func (*Synchronized[T]) Using added in v0.10.0

func (s *Synchronized[T]) Using(op func())

Using runs the provided operation while holding the lock, but without providing access to the locked value.

func (*Synchronized[T]) With added in v0.8.7

func (s *Synchronized[T]) With(in func(obj T))

With runs the input function within the lock, to mutate the object.

Directories

Path Synopsis
Package shard provides a logically versioned map implementation backed by a collection of independently synchronized maps.
Package shard provides a logically versioned map implementation backed by a collection of independently synchronized maps.

Jump to

Keyboard shortcuts

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