memory

package
v0.1.9 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: BSD-3-Clause Imports: 6 Imported by: 0

Documentation

Overview

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

StreamForce 2D

Created by Ilzr Kr.

Licensed under the BSD 3-Clause License. See LICENSE for details.

Index

Constants

View Source
const (
	// INVALID_ID is the invalid ID.
	INVALID_ID uint32 = 0
)
View Source
const (
	// MAX_LOAD_COUNT is the maximum number of times an object can be
	// loaded.
	MAX_LOAD_COUNT uint64 = 0xFFFFFFFFFFFFFFFF
)

Variables

View Source
var (
	// ErrStillInUse occurs when trying to destroy an object that does
	// not allow destruction operations while in use by other objects.
	//
	// Format:
	//   "object is still in use"
	ErrStillInUse error = errors.New("object is still in use")

	// ErrIllegalAccess occurs when trying to access an object that is
	// either destroyed or `nil`.
	//
	// Format:
	//   "object is destroyed"
	ErrIllegalAccess error = errors.New("object is destroyed")

	// ErrExcessiveUse occurs when an object has been requested to be
	// loaded too many times; usually as a byproduct of infinite loops.
	//
	// Format:
	//
	//   "excessive use of the object"
	ErrExcessiveUse error = errors.New("excessive use of the object")
)
View Source
var (
	// ErrOutOfIDs occurs when allocating a new ID fails because the
	// underlying manager is out of IDs (i.e., out of memory).
	//
	// Format:
	//   "out of IDs"
	ErrOutOfIDs error = errors.New("out of IDs")

	// ErrNoSuchID occurs when operations are performed on an ID that
	// does not exist.
	//
	// Format:
	//   "no such ID"
	ErrNoSuchID error = errors.New("no such ID")
)

Functions

func DestroySlice

func DestroySlice[S ~[]E, E Destroyer](s S)

DestroySlice is a helper function that destroys a slice of entities in parallel.

Parameters:

  • s: The slice of entities to destroy.

func IsLoaded

func IsLoaded(lc LoadCounter) bool

IsLoaded reports whether the object is loaded. If no load counter is provided, the object is defined to be not loaded.

Parameters:

  • lc: The load counter to check.

Returns:

  • bool: `true` if the object is loaded, `false` otherwise.

func LoadSlice

func LoadSlice[S ~[]E, E Loader](s S) error

LoadSlice is a helper function that loads a slice of entities in parallel.

Entities that are already loaded are ignored.

Parameters:

  • s: The slice of entities to load.

Returns:

  • error: An error if loading the entities fails.

Errors:

  • any error: The joined error with the errors that occurred while loading the entities.

func UnloadSlice

func UnloadSlice[S ~[]E, E Unloader](s S)

UnloadSlice is a helper function that unloads a slice of entities in parallel.

Parameters:

  • s: The slice of entities to unload.

Types

type Allocater

type Allocater interface {
	Destroyer

	// SetID sets the ID of the element. If the receiver is `nil`, this
	// call is a no-op.
	//
	// This call replaces the ID of the element.
	//
	// Parameters:
	//   - id: The ID of the element.
	SetID(id uint32)

	// GetID returns the ID of the element. If the receiver is `nil`,
	// [memory.INVALID_ID] is returned.
	//
	// Returns:
	//   - uint32: The ID of the element.
	GetID() uint32
}

Allocater is the interface that defines the basic behaviors of allocable elements.

type Allocator

type Allocator[E Allocater] struct {
	// contains filtered or unexported fields
}

Allocator is a generic manager for allocating and deallocating elements.

An allocator does not need a constructor to be used.

func (*Allocator[E]) All

func (m *Allocator[E]) All() iter.Seq[E]

All returns an iterator over the allocated elements.

The manager is read-locked for the duration of the call and the return order of the elements is undefined.

Returns:

  • iter.Seq[E]: The iterator over the allocated elements. It is never `nil`.

func (*Allocator[E]) Allocate

func (m *Allocator[E]) Allocate(elem E) (uint32, error)

Allocate allocates a new element and returns its ID.

Parameters:

  • elem: The element to allocate.

Returns:

  • uint32: The ID of the allocated element.
  • error: An error if allocating the element fails.

Errors:

  • errors.ErrNilReceiver: If the receiver is `nil`.
  • errors.New: If the element is already allocated.
  • memory.ErrOutOfIDs: If the ID manager is out of IDs.

func (*Allocator[E]) Deallocate

func (m *Allocator[E]) Deallocate(target uint32)

Deallocate deallocates the element with the given ID. If the receiver is `nil`, this call is a no-op.

If the ID is invalid or it does not exist, this call is a no-op.

Parameters:

  • target: The ID of the element to deallocate.

func (*Allocator[E]) Destroy added in v0.1.7

func (m *Allocator[E]) Destroy()

Destroy implements Destroyer.

func (*Allocator[E]) Get

func (m *Allocator[E]) Get(target uint32) (E, bool)

Get returns the element with the given ID.

Parameters:

  • target: The ID of the element to get.

Returns:

  • E: The element with the given ID.
  • bool: `true` if the element was found, `false` otherwise.

func (*Allocator[E]) IsEmpty added in v0.1.9

func (m *Allocator[E]) IsEmpty() bool

IsEmpty reports whether the allocator is empty. If the receiver is `nil`, the allocator is defined to be empty.

Returns:

  • bool: `true` if the allocator is empty, `false` otherwise.

func (*Allocator[E]) Length

func (m *Allocator[E]) Length() uint32

Length returns the number of allocated elements. If the receiver is `nil`, the manager is defined to be empty.

Returns:

func (*Allocator[E]) MustGet

func (m *Allocator[E]) MustGet(target uint32) E

MustGet returns the element with the given ID and panics if it is not possible to retrieve the element.

Parameters:

  • target: The ID of the element to get.

Returns:

  • E: The element with the given ID.

Panics:

  • errors.ErrNilReceiver: If the receiver is `nil`.
  • ErrNoSuchID: If the ID does not exist.

type Destroyer

type Destroyer interface {
	// Destroy performs the necessay clean-up tasks for destroying the
	// object in question; thus, making it available for garbage
	// collection.
	//
	// For consistency reasons, `nil` receivers are considered to be
	// already released and so, they will not return an error. Finally,
	// it is not possible to destroy an object that is still in use.
	//
	// WARNING: The destruction operation must not be used as the
	// default unload mechanism as, upon a successful call, the objects
	// are deemed to be unavailable for further use; thus, any attempt
	// to use them might result in errors or undefined behaviors.
	//
	// Returns:
	//   - error: An error if destroying the object fails.
	//
	// Errors:
	//   - any error: Depends on the implementation.
	Destroy()
}

Destroyer is the inferface that wraps the basic destroy method.

This is best used for when objects are not needed anymore and won't be needed ever again; especially when said objects are big.

Implementations must unload the object's memory in a safe way when destroying the object, including if the object is not in a valid state. This prevents a bunch of memory leaks and issues later on.

Furthermore, implementations should refrain from performing any I/O operations unless they are strictly necessary, for safety reasons, or for debugging purposes. This means that logging or printing inside destroy methods is generally not a good idea.

Because objects can be shared between goroutines, actual resources are destroyed only when the reference count reaches zero.

Finally, destroy methods should refrain from returning errors, ideally no error. This is due to the fact that, if destroying an object fails, it could leave is in a broken state that could cause issues down the line.

As such, it is a good practive to solve all the issues at the best of your abilities and only return an error if you have no choice but to do so.

type IDManager

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

IDManager is a component of the Memory Management System (MMS) that allows to manage identifiers in an efficient way.

An ID manager does not need a constructor to be used.

func (*IDManager) Allocate

func (idm *IDManager) Allocate() uint32

Allocate allocates a new identifier and returns it. If the receiver is `nil`, INVALID_ID is returned.

If the ID manager has no free IDs, INVALID_ID is returned.

Returns:

  • uint32: The identifier allocated for the entry, if successful.

func (*IDManager) Contains

func (idm *IDManager) Contains(target uint32) bool

Contains reports whether the ID is allocated. If the receiver is `nil`, the ID manager is defined to contain no IDs.

Invalid IDs are never allocated.

Parameters:

  • target: The target ID.

Returns:

  • bool: `true` if the ID is allocated, `false` otherwise.

func (*IDManager) Deallocate

func (idm *IDManager) Deallocate(target uint32) (uint32, uint32, bool)

Deallocate deallocates the ID from the manager and returns the index of the deleted ID and the index of the last ID.

Parameters:

  • target_id: The ID to delete.

Returns:

  • uint32: The index of the deleted ID.
  • uint32: The index of the last ID.
  • bool: `true` if successful, `false` otherwise.

func (*IDManager) Get

func (idm *IDManager) Get(target uint32) (uint32, bool)

Get returns the index with the associated ID, if it exists. If the receiver is `nil`, no index is returned.

If the ID is not valid, no index is returned.

Parameters:

  • target_id: The target ID.

Returns:

  • uint32: The index with the associated ID, if it exists.
  • bool: `true` if successful, `false` otherwise.

func (*IDManager) IsEmpty added in v0.1.9

func (idm *IDManager) IsEmpty() bool

IsEmpty reports whether the ID manager is empty. If the receiver is `nil`, the ID manager is defined to be empty.

Returns:

  • bool: `true` if the ID manager is empty, `false` otherwise.

func (*IDManager) Length

func (idm *IDManager) Length() uint32

Length returns the number of allocated IDs. If the receiver is `nil`, the ID manager is defined to be empty.

Returns:

func (*IDManager) Random

func (idm *IDManager) Random() uint32

Random returns an ID picked at random. If the receiver is `nil`, INVALID_ID is returned.

If the ID manager has no allocated IDs, INVALID_ID is returned.

The returned ID is not truly random as it depends on the allocation and deallocation order. With enough allocations and deallocations, however, the returned ID is random enough for most purposes.

Returns:

  • uint32: The ID picked at random.

type LoadCounter

type LoadCounter interface {
	// LoadCount returns the number of loads performed on the object. If
	// the receiver is `nil`, it returns 0.
	//
	// Returns:
	//   - uint64: The number of loads performed on the object.
	LoadCount() uint64
}

LoadCounter is the interface that wraps the basic load count method.

type Loader

type Loader interface {
	// Load initializes the object's memory.
	//
	// Loading is done by performing the setup tasks; thus, making it
	// ready for use. These operations include, but not limited to,
	// gathering resources and checking preconditions.
	//
	// Because an object can be load multiple times, actual resources are
	// loaded only at the first load call. If loading is successful, the
	// object is both loaded in memory and valid for use; thus, any
	// operation performed on the object afterwards should not fail
	// (i.e., does not return errors that are cause by invalid states or
	// missing resources).
	//
	// The method returns the number of loads performed on the object
	// AFTER the current load call.
	//
	// 	0: Loading failed.
	// 	1: Loading done for the first time.
	// 	any other value: Loading done multiple times.
	//
	// Returns:
	//    - uint64: The number of loads performed on the object.
	// 	- error: An error if loading the object fails.
	//
	// Errors:
	//    - errors.ErrNilReceiver: If the receiver is `nil`.
	//    - ErrIllegalAccess: If the object has been destroyed.
	//    - ErrExcessiveUse: If the object has been loaded too many
	//      times.
	//    - any other error: Depends on the implementation.
	Load() (uint64, error)
}

Loader is the interface that wraps the basic load method.

Implementations should refrain from performing any I/O operations, unless they are strictly necessary for initializing the object, for safety reasons, or for debugging. This means that logging or printing inside load methods is generally not a good idea.

type Unloader

type Unloader interface {
	// Unload unloads the object's memory. If the receiver is `nil` or
	// not loaded, nothing happens.
	//
	// Unloading is done by performing any necessary cleanup tasks; thus,
	// making it no longer usable. These operations include, but not
	// limited to, destroying resources and checking postconditions.
	//
	// Because an object can be loaded multiple times, actual resources
	// are unloaded only at the last unload call. If unloading is
	// successful, the object is both unloaded from memory and no longer
	// valid for use. Still, the object is not entirely lost and can be
	// loaded again if needed with a call to load methods.
	//
	// The method returns the number of loads performed on the object
	// AFTER the current unload call. So, a value of 0 means that the
	// object is not used by anyone anymore.
	//
	// Returns:
	//   - uint64: The number of remaining objects that have requested
	// 	the object.
	Unload() uint64
}

Unloader is the interface that wraps the basic unload method.

Implementations should refrain from performing any I/O operations, unless they are strictly necessary for initializing the object, for safety reasons, or for debugging. This means that logging or printing inside load methods is generally not a good idea.

Jump to

Keyboard shortcuts

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