freelist

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2023 License: BSD-3-Clause Imports: 4 Imported by: 0

README

freelist

package freelist implements a efficient, thread-safe free list, similar to sync.Pool.

Install

go get github.com/weiwenchen2022/freelist

Reference

GoDoc: https://godoc.org/github.com/weiwenchen2022/freelist

Documentation

Overview

Example
package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"log"

	"github.com/weiwenchen2022/freelist"
)

type P struct {
	X, Y, Z int
	Name    string
}

type Q struct {
	X, Y *int32
	Name string

	next *Q // for free list
}

var freeQ = &freelist.FreeList[Q]{
	New: func() *Q {
		return new(Q)
	},
	Reset: func(q *Q) {
		*q = Q{}
	},
}

func main() {
	// Initialize the encoder and decoder. Normally enc and dec would be
	// bound to network connections and the encoder and decoder would
	// run in different processes.
	var network bytes.Buffer        // Stand-in for a network connection
	enc := gob.NewEncoder(&network) // Will write to network.
	dec := gob.NewDecoder(&network) // Will read from network.

	// Encode (send) some values.
	if err := enc.Encode(P{3, 4, 5, "Pythagoras"}); err != nil {
		log.Fatal("encode error:", err)
	}

	if err := enc.Encode(P{1782, 1841, 1922, "Treehouse"}); err != nil {
		log.Fatal("encode error:", err)
	}

	// Decode (receive) and print the values.
	var q = freeQ.Get()
	defer freeQ.Put(q)

	if err := dec.Decode(q); err != nil {
		log.Fatal("decode error 1:", err)
	}
	fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)

	q = freeQ.Get()
	defer freeQ.Put(q)

	if err := dec.Decode(q); err != nil {
		log.Fatal("decode error 2:", err)
	}
	fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)

}
Output:

"Pythagoras": {3, 4}
"Treehouse": {1782, 1841}
Example (Wrapper)
package main

import (
	"bytes"
	"io"
	"os"
	"time"

	"github.com/weiwenchen2022/freelist"
)

type Buf struct {
	*bytes.Buffer
	next *Buf // for free list
}

var freeBuf = freelist.FreeList[Buf]{
	New: func() *Buf {
		return &Buf{Buffer: new(bytes.Buffer)}
	},

	Reset: (*Buf).Reset,
}

// timeNow is a fake version of time.Now for tests.
func timeNow() time.Time {
	return time.Unix(1136214245, 0)
}

func Log(w io.Writer, key, val string) {
	b := freeBuf.Get()
	defer freeBuf.Put(b)

	// Replace this with time.Now() in a real logger.
	b.WriteString(timeNow().UTC().Format(time.RFC3339))
	b.WriteByte(' ')
	b.WriteString(key)
	b.WriteByte('=')
	b.WriteString(val)
	_, _ = io.Copy(w, b)
}

func main() {
	Log(os.Stdout, "path", "/search?q=flowers")
}
Output:

2006-01-02T15:04:05Z path=/search?q=flowers

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FreeList

type FreeList[E any] struct {

	// New optionally specifies a function to generate
	// a value when Get would otherwise return nil.
	// It may not be changed concurrently with calls to Get.
	New func() *E

	// Reset optionally specifies a function to reset
	// a value when Get would return a cached value.
	// It may not be changed concurrently with calls to Get.
	Reset func(*E)
	// contains filtered or unexported fields
}

A FreeList is a set of temporary objects that may be individually saved and retrieved.

Any item stored in the FreeList must be a struct look schematically like

type T struct {
	...
	next *T
	...
}

A FreeList is safe for use by multiple goroutines simultaneously.

FreeList's purpose is to cache allocated but unused items for later reuse, relieving pressure on the garbage collector. That is, it makes it easy to build efficient, thread-safe free lists.

An appropriate use of a FreeList is to manage a group of temporary items silently shared among and potentially reused by concurrent independent clients of a package. FreeList provides a way to amortize allocation overhead across many clients.

On the other hand, a free list maintained as part of a short-lived object is not a suitable use for a FreeList, since the overhead does not amortize well in that scenario. It is more efficient to have such objects implement their own free list.

A FreeList must not be copied after first use.

In the terminology of the Go memory model, a call to Put(x) “synchronizes before” a call to Get returning that same value x. Similarly, a call to New returning x “synchronizes before” a call to Get returning that same value x.

func (*FreeList[E]) Get

func (l *FreeList[E]) Get() *E

Get selects a last put back item from the FreeList, removes it from the FreeList, if l.Reset is non-nil calling l.Reset with it, and returns it to the caller.

If Get would otherwise return nil and l.New is non-nil, Get returns the result of calling l.New.

func (*FreeList[E]) Put

func (l *FreeList[E]) Put(x *E)

Put adds x to the free list.

Jump to

Keyboard shortcuts

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