freelist package - github.com/Snawoot/freelist - Go Packages

3 min read Original article ↗

Package freelist provides generic implementation of freelist allocator in pure Go.

It is useful for implementation of algorithms and data structures using a lot of small objects. To some extent it is similar to sync.Pool. But unlike sync.Pool, this package provides more predictable retention, type safety and control over lifecycle of allocated objects. On the other hand, this package requires allocated objects to be explicitly freed to avoid memory leaks.

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"strings"

	"github.com/Snawoot/freelist"
)

func main() {
	const jsonStream = `
	{"Name": "Ed", "Text": "Knock knock."}
	{"Name": "Sam", "Text": "Who's there?"}
	{"Name": "Ed", "Text": "Go fmt."}
	{"Name": "Sam", "Text": "Go fmt who?"}
	{"Name": "Ed", "Text": "Go fmt yourself!"}
`
	type Message struct {
		Name, Text string
	}
	dec := json.NewDecoder(strings.NewReader(jsonStream))
	var messages []*Message
	var allocator freelist.Freelist[Message]
	for {
		m := allocator.Alloc()
		if err := dec.Decode(m); err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}
		messages = append(messages, m)
	}
	for _, m := range messages {
		fmt.Printf("%s: %s\n", m.Name, m.Text)
		allocator.Free(m)
	}
	messages = nil // make sure pointers released
}

This section is empty.

This section is empty.

This section is empty.

type Freelist[T any] struct {
	
	
	
	
	
	
	
	
	
	
	
	
	
	NextCapFn func(currentCap int) int
	
}

A Freelist is an instance of freelist allocator of objects of type T. The zero value for Freelist is an empty freelist ready to use.

A Freelist should not be copied after first use.

Methods of Freelist are not safe for concurrent use by multiple goroutines.

func (fl *Freelist[T]) Alloc() *T

Alloc allocates new object. Allocated pointers should be eventually disposed with either:

  • Passing pointer to Freelist.Free.
  • Clearing entire freelist with Freelist.Clear.
  • Dropping reference to entire Freelist and all objects allocated from it.
func (fl *Freelist[T]) Cap() int

Cap returns the number of objects that freelist currently can hold.

func (fl *Freelist[T]) Clear()

Clear resets freelist to initial empty state.

func (fl *Freelist[T]) Free(x *T)

Free deallocates object previously allocated by Freelist.Alloc. Free immediately overwrites freed memory with zero value of corresponding type T and marks memory as available for reuse.

Pointer to deallocated object should not be used after call to Free.

func (fl *Freelist[T]) Grow(n int)

Grow grows the freelist's capacity to guarantee space for another n objects. After Grow(n), at least n objects can be allocated from freelist without another allocation from runtime. If n is negative, Grow will panic.

func (fl *Freelist[T]) Len() int

Len returns the number of objects currently allocated from freelist.