Skip to content

Colduction/boundedpool-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

boundedpool-go

Go Reference GitHub License

Generic, exact-capacity object pool for Go.

Retained TryGet hits use bounded atomic probes without callbacks or allocations. TryPut has the same fast path unless WithHookOnPut is configured. An empty TryGet calls the factory supplied to New.

Install

go get github.com/colduction/boundedpool-go@latest

Quick start

package main

import (
	"bytes"

	"github.com/colduction/boundedpool-go"
)

func main() {
	pool, err := boundedpool.New(1024,
		func() *bytes.Buffer {
			return new(bytes.Buffer)
		},
		boundedpool.WithHookOnPut(func(buf *bytes.Buffer) {
			buf.Reset()
		}),
	)
	if err != nil {
		panic(err)
	}

	buf, err := pool.TryGet()
	if err != nil {
		return
	}
	buf.WriteString("hello")
	switch err := pool.TryPut(buf); err {
	case nil:
		// Pool owns buf.
	case boundedpool.ErrUnavailable, boundedpool.ErrClosed:
		// Caller still owns buf and may dispose or retry it.
	}

	items, first := pool.Close()
	if first {
		for _, item := range items {
			// Dispose retained items when T owns external resources.
			_ = item
		}
	}
}

Contract

Call Result
TryGet A nil error returns an idle item or a factory-created item.
TryPut A nil error transfers item to pool. Rejection keeps caller ownership.
Close Seals storage and returns every retained item to winning caller.
Len Approximate idle count; zero once Closed reports true.
Cap Exact maximum retained item count.
Closed Whether new operations are rejected.

New requires a factory that returns a fully initialized, usable, non-nil value. The factory may run concurrently and controls its own blocking and allocations. It must not panic or call methods on the same pool. Items passed to TryPut must also be usable and non-nil.

WithHookOnPut runs a callback after TryPut reserves idle storage and before the item becomes available to TryGet. Use it to reset, clear, or resize pointer-backed values. Rejected puts do not run it, so caller-owned values remain unchanged. The callback may run concurrently and must not panic or call methods on the same pool.

When TryGet wins no retained item during its bounded scan, it calls the factory. Concurrent misses may create more live values than Cap; capacity bounds retained idle values, not checked-out values.

ErrUnavailable is returned only by TryPut when no slot was won. In a quiescent pool this means full; concurrent ownership transfers can make that observation stale immediately. TryPut returns package sentinels directly, so hot callers may compare them with == instead of errors.Is.

Close performs no callbacks. It marks every slot closed, waits for in-progress ownership transfers, put hooks, and factory calls, compacts retained items in the existing backing array, then returns them without allocating. Concurrent losing Close calls wait for drain completion and return nil, false. Checked-out and rejected items remain caller-owned.

An operation overlapping Close may return a transfer that linearized first or ErrClosed; it cannot access returned storage after Close finishes.

Options

Option Default Purpose
WithHookOnPut - Runs a hook on each accepted item before retention.
WithShardFactor 2 Requests factor × GOMAXPROCS shards.
WithNumShards - Requests explicit shard count; overrides factor.

Shard count is normalized to a power of two, capped by capacity, and raised when needed to keep each shard at most 64 slots. Every call probes at most Cap slots. This preserves deterministic capacity and ownership; the scans themselves are O(Cap) and never wait or allocate.

Never use an item after successful TryPut, put one item twice, or copy a pool after first use. Prefer pointers for values containing mutexes, atomics, or other non-copyable state.

Compared with sync.Pool

sync.Pool may discard cached values at any GC cycle. boundedpool-go retains idle items up to exact configured capacity until Close, then returns them to caller control.

License

GNU Lesser General Public License v2.1. See LICENSE.

About

A high-performance, thread-safe, bounded object pool implementation for Go, designed as a flexible alternative to "sync.Pool"

Resources

License

Stars

4 stars

Watchers

1 watching

Forks

Contributors

Languages