usagepool

package
v0.0.0-...-e4d3d8e Latest Latest
Warning

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

Go to latest
Published: May 15, 2023 License: MIT Imports: 3 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Constructor

type Constructor func() (Destructor, error)

Constructor is a function that returns a new value that can destruct itself when it is no longer needed.

type Destructor

type Destructor interface {
	Destruct() error
}

Destructor is a value that can clean itself up when it is deallocated.

type UsagePool

type UsagePool struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

UsagePool is a thread-safe map that pools values based on usage (reference counting). Values are only inserted if they do not already exist. There are two ways to add values to the pool:

  1. LoadOrStore will increment usage and store the value immediately if it does not already exist.
  2. LoadOrNew will atomically check for existence and construct the value immediately if it does not already exist, or increment the usage otherwise, then store that value in the pool. When the constructed value is finally deleted from the pool (when its usage reaches 0), it will be cleaned up by calling Destruct().

The use of LoadOrNew allows values to be created and reused and finally cleaned up only once, even though they may have many references throughout their lifespan. This is helpful, for example, when sharing thread-safe io.Writers that you only want to open and close once.

There is no way to overwrite existing keys in the pool without first deleting it as many times as it was stored. Deleting too many times will panic.

The implementation does not use a sync.Pool because UsagePool needs additional atomicity to run the constructor functions when creating a new value when LoadOrNew is used. (We could probably use sync.Pool but we'd still have to layer our own additional locks on top.)

An empty UsagePool is NOT safe to use; always call NewUsagePool() to make a new one.

func NewUsagePool

func NewUsagePool() *UsagePool

NewUsagePool returns a new usage pool that is ready to use.

func (*UsagePool) Delete

func (up *UsagePool) Delete(key any) (deleted bool, err error)

Delete decrements the usage count for key and removes the value from the underlying map if the usage is 0. It returns true if the usage count reached 0 and the value was deleted. It panics if the usage count drops below 0; always call Delete precisely as many times as LoadOrStore.

func (*UsagePool) LoadOrNew

func (up *UsagePool) LoadOrNew(key any, construct Constructor) (value any, loaded bool, err error)

LoadOrNew loads the value associated with key from the pool if it already exists. If the key doesn't exist, it will call construct to create a new value and then stores that in the pool. An error is only returned if the constructor returns an error. The loaded or constructed value is returned. The loaded return value is true if the value already existed and was loaded, or false if it was newly constructed.

func (*UsagePool) LoadOrStore

func (up *UsagePool) LoadOrStore(key, val any) (value any, loaded bool)

LoadOrStore loads the value associated with key from the pool if it already exists, or stores it if it does not exist. It returns the value that was either loaded or stored, and true if the value already existed and was

func (*UsagePool) Range

func (up *UsagePool) Range(f func(key, value any) bool)

Range iterates the pool similarly to how sync.Map.Range() does: it calls f for every key in the pool, and if f returns false, iteration is stopped. Ranging does not affect usage counts.

This method is somewhat naive and acquires a read lock on the entire pool during iteration, so do your best to make f() really fast, m'kay?

func (*UsagePool) References

func (up *UsagePool) References(key any) (int, bool)

References returns the number of references (count of usages) to a key in the pool, and true if the key exists, or false otherwise.

Jump to

Keyboard shortcuts

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