mmm

package
v0.0.0-...-1fab7fd Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2024 License: 0BSD Imports: 2 Imported by: 2

Documentation

Overview

Package mmm provides a way to manually manage memory and resource lifetimes with protections against unsafe double-free and use-after-free errors.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func API

func API[API any, T PointerWithFree[API, T, Size], Size PointerSize](ptr T) *API

API returns the API associated with the given pointer.

func Copy

func Copy[API any, T PointerWithFree[API, T, Size], Size PointerSize](ptr T, lifetime Lifetime) T

Copy returns a copy of the given pointer that is bound to a new lifetime. T.Free will be called once all copies of the pointer have been freed. The pointer must have been created with New otherwise this function will panic.

func End

func End[API any, T PointerWithFree[API, T, Size], Size PointerSize](ptr T) Size

End the lifetime of a pointer, this function must be called from within the Free method of a PointerWithFree. Does not free any underlying resources associated with the pointer, use [Free] for that.

func Get

func Get[T ManagedPointer[Size], Size PointerSize](ptr T) Size

Get the underlying pointer value from a manually managed pointer. If the pointer has already been freed, this function will (safely) panic.

func Let

func Let[T PointerWithFree[API, T, Size], API any, Size PointerSize](lifetime Lifetime, api *API, ptr Size) T

Let takes a raw 'Size' pointer value that points at foreign memory or an external resource that is permitted to be borrowed until the end of the specified lifetime. The pointer returned by this function may not be moved to another lifetime, nor may it be freed.

Pointers passed to this function retain ownership of the original 'ptr' value, however such code may not free the pointer until Lifetime.End has been called.

func Move

func Move[API any, T PointerWithFree[API, T, Size], Size PointerSize](ptr T, lifetime Lifetime)

Move the given pointer from its previously bound lifetime to a new lifetime, it will no longer be freed when its previous lifetime ends and will instead be freed when the new one ends. The pointer must have been created with New otherwise this function will panic. The pointer may not have been copied.

func New

func New[T PointerWithFree[API, T, Size], API any, Size PointerSize](lifetime Lifetime, api *API, ptr Size) T

New takes a raw 'Size' pointer value that points at memory or a resource that needs to be manually managed. The pointer will be assoicated with the specified lifetime, when the lifetime ends the pointer's Free method will be called "exactly once". Invalid usage of the pointer remains safe and will raise a runtime panic that can be recovered from.

Pointers passed to this function transfer ownership of [T.Free] to T, copies of 'ptr' must behave as if T.Free was called immediately on the pointer after being passed to this function.

func Pin

func Pin[T PointerWithFree[API, T, Size], API any, Size PointerSize](lifetime Lifetime, api *API, ptr Size) T

Pin behaves like New except that the pointer is pinned to the lifetime and may not be moved to another one. [T.Free] will be called when the lifetime ends.

func Set

func Set[API any, T PointerWithFree[API, T, Size], Size PointerSize](ptr *T, value Size)

Set the pointer value to the given 'ptr' value, the pointer must have been created with New otherwise this function will panic.

Types

type Lifetime

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

Lifetime group, keeps track of a sequence of Pointer values and calls their [Free] methods when their lifetime has ended. Not safe for use by multiple goroutines. Beware of using Lifetime types to manage the lifetime of other Lifetime values, as this may can lead to reference cycles (a form of manual memory management deadlock) that will prevent the lifetime from ever ending.

Usually you'll want to create a Lifetime and immediately defer its End and pass it down the call stack as if it were a context.Context (or inside of one). If the lifetime is never ended, the underlying Pointer values will never be freed and will leak.

func Life

func Life[API any, T PointerWithFree[API, T, Size], Size PointerSize](ptr T) Lifetime

Life returns the lifetime of the given 'pinned' pointer, panics if the pointer is not pinned.

func NewLifetime

func NewLifetime() Lifetime

NewLifetime returns a new lifetime, call End to free any [Pointers] associated with this lifetime. The Lifetime may no longer be used after calling End.

func (Lifetime) End

func (lifetime Lifetime) End()

End the lifetime, freeing any unfreed [Pointers] associated with it. This is an idempotent operation, calling it multiple times is safe.

type ManagedPointer

type ManagedPointer[Size PointerSize] interface {
	// contains filtered or unexported methods
}

ManagedPointer is any Pointer value with a PointerSize of 'Size'.

type Pointer

type Pointer[API any, T PointerWithFree[API, T, Size], Size PointerSize] struct {
	// contains filtered or unexported fields
}

Pointer of unique type T belonging to the given API, using the given RAM allocator that is reponsible for freeing the pointer.

type PointerSize

type PointerSize interface {
	~uintptr | ~[0]uintptr | ~[1]uintptr | ~[2]uintptr | ~[3]uintptr
}

PointerSize is a valid pointer size.

type PointerWithFree

type PointerWithFree[API any, T any, Size PointerSize] interface {
	~struct {
		// contains filtered or unexported fields
	}

	ManagedPointer[Size]

	// Free should release any underlying resources associated with the pointer
	// and call [End] on the pointer. Calling this multiple times is safe but will
	// raise a recoverable runtime panic.
	Free()
}

PointerWithFree is a value with an underlying Pointer type and a [Free] method that calls End on the pointer.

Jump to

Keyboard shortcuts

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