msync

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package msync provides concurrency control utilities for managing concurrent operations in Go applications.

The package includes the following components:

  • SingleFlight: Prevents duplicate function calls for the same key, useful for preventing cache stampede.

  • LockedCalls: Ensures sequential execution of operations with the same key, useful for write operations that must be serialized.

  • Limit: Controls the maximum number of concurrent operations, useful for rate limiting and resource management.

  • Pool: Manages a pool of reusable objects with capacity limits and expiration, useful for connection pools and buffer pools.

Basic usage examples:

// SingleFlight - prevent cache stampede
sf := msync.NewSingleFlight()
result, err := sf.Do("cache-key", func() (any, error) {
    return queryDatabase()
})

// LockedCalls - serialize operations
lc := msync.NewLockedCalls()
_, err := lc.Do("user-123", func() (any, error) {
    return updateUserBalance(amount)
})

// Limit - control concurrency
limit := msync.NewLimit(10) // max 10 concurrent
limit.Borrow()
defer limit.Return()
// perform operation

// Pool - object pool
pool := msync.NewPool(50,
    func() any { return createConnection() },
    func(x any) { x.(*Connection).Close() },
    msync.WithMaxAge(5*time.Minute),
)
conn := pool.Get()
defer pool.Put(conn)
// use connection

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrLimitReturn is returned when Return is called without a corresponding Borrow.
	ErrLimitReturn = errors.New("msync: limit return without borrow")
)

Functions

This section is empty.

Types

type Limit

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

Limit is a semaphore implementation using channels to limit concurrent execution. It allows controlling the maximum number of concurrent operations.

func NewLimit

func NewLimit(n int) *Limit

NewLimit creates and returns a new Limit instance with the specified capacity. The capacity determines the maximum number of concurrent operations allowed.

func (*Limit) Borrow

func (l *Limit) Borrow()

Borrow acquires a slot from the limit pool, blocking if the pool is full. It must be paired with a Return call to release the slot.

func (*Limit) Return

func (l *Limit) Return() error

Return releases a slot back to the limit pool. It returns an error if Return is called more times than Borrow.

func (*Limit) TryBorrow

func (l *Limit) TryBorrow() bool

TryBorrow attempts to acquire a slot from the limit pool without blocking. It returns true if successful, false if the pool is full.

type LockedCalls

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

LockedCalls ensures that calls with the same key are executed sequentially. Unlike SingleFlight, each call executes the function independently and gets its own result. This is useful for write operations where each operation must be executed, but operations with the same key must be serialized.

func NewLockedCalls

func NewLockedCalls() *LockedCalls

NewLockedCalls creates and returns a new LockedCalls instance.

func (*LockedCalls) Do

func (lc *LockedCalls) Do(key string, fn func() (any, error)) (any, error)

Do executes the given function for the specified key. If another goroutine is already executing a function for the same key, this call will wait for it to complete before executing. Each call executes the function independently and receives its own result.

type Pool

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

Pool is an object pool with capacity limit and expiration support. Unlike sync.Pool, it: - Supports capacity limits - Supports object expiration based on idle time - Supports custom create and destroy callbacks - Will not be cleared by GC

func NewPool

func NewPool(limit int, create func() any, destroy func(any), opts ...PoolOption) *Pool

NewPool creates and returns a new Pool instance.

Parameters:

  • limit: Maximum number of objects that can exist
  • create: Function to create new objects
  • destroy: Function to destroy objects (can be nil)
  • opts: Optional configuration options

func (*Pool) Available

func (p *Pool) Available() int

Available returns the number of idle objects currently in the pool.

func (*Pool) Clear

func (p *Pool) Clear()

Clear removes all idle objects from the pool and destroys them.

func (*Pool) Get

func (p *Pool) Get() any

Get retrieves an object from the pool. If the pool is empty and the limit hasn't been reached, a new object is created. If the pool is empty and the limit has been reached, Get blocks until an object is available.

func (*Pool) Put

func (p *Pool) Put(x any)

Put returns an object to the pool. If x is nil, it is ignored.

func (*Pool) Size

func (p *Pool) Size() int

Size returns the current number of objects in the pool (both idle and in use).

type PoolOption

type PoolOption func(*Pool)

PoolOption is a function type for configuring Pool.

func WithMaxAge

func WithMaxAge(d time.Duration) PoolOption

WithMaxAge sets the maximum idle time for objects in the pool. Objects idle longer than this duration will be destroyed when retrieved.

type SingleFlight

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

SingleFlight prevents duplicate function calls for the same key. Multiple concurrent calls with the same key will share the result of a single execution.

func NewSingleFlight

func NewSingleFlight() *SingleFlight

NewSingleFlight creates and returns a new SingleFlight instance.

func (*SingleFlight) Do

func (sf *SingleFlight) Do(key string, fn func() (any, error)) (any, error)

Do executes and returns the results of the given function, making sure that only one execution is in-flight for a given key at a time. If a duplicate comes in, the duplicate caller waits for the original to complete and receives the same results.

func (*SingleFlight) DoEx

func (sf *SingleFlight) DoEx(key string, fn func() (any, error)) (val any, fresh bool, err error)

DoEx is like Do but returns whether the result is fresh (newly executed). The fresh boolean will be true if the caller executed the function, or false if it waited for another caller's result.

Jump to

Keyboard shortcuts

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