Documentation
¶
Overview ¶
Package semaphore provides a process-local FIFO weighted semaphore with explicit permit ownership and deterministic shutdown.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/faustbrian/go-semaphore"
)
func main() {
sem, err := semaphore.New(semaphore.Config{Capacity: 4, MaxWaiters: 32})
if err != nil {
panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
value, err := semaphore.Execute(ctx, sem, 2, func(context.Context) (string, error) {
return "finished", nil
})
if err != nil {
panic(err)
}
fmt.Println(value, sem.Snapshot().Available)
}
Output: finished 4
Index ¶
- Constants
- Variables
- func Execute[T any](ctx context.Context, semaphore *Semaphore, weight int64, ...) (result T, err error)
- type CanceledError
- type ClosedError
- type Config
- type ConfigError
- type ConfigField
- type ConfigProblem
- type DuplicateReleaseError
- type Event
- type EventKind
- type Observer
- type ObserverFunc
- type Permit
- type PermitID
- type QueueFullError
- type Reason
- type Semaphore
- func (semaphore *Semaphore) Acquire(ctx context.Context, weight int64) (*Permit, error)
- func (semaphore *Semaphore) Close() error
- func (semaphore *Semaphore) Run(ctx context.Context, weight int64, operation func(context.Context) error) error
- func (semaphore *Semaphore) Snapshot() Snapshot
- func (semaphore *Semaphore) TryAcquire(weight int64) (*Permit, bool, error)
- func (semaphore *Semaphore) Wait(ctx context.Context) error
- type Snapshot
- type WeightError
Examples ¶
Constants ¶
const MaxWaiters = 1_000_000
MaxWaiters is the largest supported bounded FIFO queue.
Variables ¶
var ( // ErrInvalidConfig classifies construction failures. ErrInvalidConfig = errors.New("semaphore: invalid configuration") // ErrDuplicateRelease classifies repeated release of one permit. ErrDuplicateRelease = errors.New("semaphore: duplicate permit release") // ErrInvalidWeight classifies non-positive acquisition weights. ErrInvalidWeight = errors.New("semaphore: invalid weight") // ErrOversize classifies weights larger than total capacity. ErrOversize = errors.New("semaphore: weight exceeds capacity") // ErrQueueFull classifies bounded-waiter saturation. ErrQueueFull = errors.New("semaphore: waiter queue full") // ErrCanceled classifies acquisition cancellation. ErrCanceled = errors.New("semaphore: context canceled") // ErrDeadline classifies acquisition deadline expiry. ErrDeadline = errors.New("semaphore: context deadline exceeded") // ErrClosed classifies admission after deterministic shutdown. ErrClosed = errors.New("semaphore: closed") )
Functions ¶
func Execute ¶
func Execute[T any](ctx context.Context, semaphore *Semaphore, weight int64, operation func(context.Context) (T, error)) (result T, err error)
Execute acquires weight, invokes operation, and releases on success, error, or panic. It preserves the returned value and error or the original panic.
Types ¶
type CanceledError ¶
type CanceledError struct {
Deadline bool
}
CanceledError distinguishes cancellation from deadline expiry while preserving compatibility with the corresponding context error.
func (*CanceledError) Error ¶
func (err *CanceledError) Error() string
Error returns a stable cancellation diagnostic.
func (*CanceledError) Is ¶
func (err *CanceledError) Is(target error) bool
Is supports package and context cancellation classification.
type ClosedError ¶
type ClosedError struct{}
ClosedError reports that the semaphore no longer accepts work.
func (*ClosedError) Error ¶
func (err *ClosedError) Error() string
Error returns a stable shutdown diagnostic.
func (*ClosedError) Unwrap ¶
func (err *ClosedError) Unwrap() error
Unwrap exposes ErrClosed for errors.Is.
type ConfigError ¶
type ConfigError struct {
// contains filtered or unexported fields
}
ConfigError describes one invalid, bounded configuration field without retaining arbitrary caller-controlled text.
func (*ConfigError) Error ¶
func (err *ConfigError) Error() string
Error returns a bounded configuration diagnostic.
func (*ConfigError) Field ¶
func (err *ConfigError) Field() ConfigField
Field returns the invalid bounded configuration field.
func (*ConfigError) Problem ¶
func (err *ConfigError) Problem() ConfigProblem
Problem returns the bounded validation problem.
func (*ConfigError) Unwrap ¶
func (err *ConfigError) Unwrap() error
Unwrap exposes ErrInvalidConfig for errors.Is.
type ConfigField ¶
type ConfigField string
ConfigField identifies a bounded configuration field.
const ( // FieldCapacity identifies Config.Capacity. FieldCapacity ConfigField = "capacity" // FieldMaxWaiters identifies Config.MaxWaiters. FieldMaxWaiters ConfigField = "max waiters" )
type ConfigProblem ¶
type ConfigProblem string
ConfigProblem identifies a bounded configuration violation.
const ( // ProblemMustBePositive identifies a required positive value. ProblemMustBePositive ConfigProblem = "must be positive" // ProblemMustNotBeNegative identifies a required non-negative value. ProblemMustNotBeNegative ConfigProblem = "must not be negative" // ProblemExceedsBound identifies a value above the supported bound. ProblemExceedsBound ConfigProblem = "exceeds the supported bound" )
type DuplicateReleaseError ¶
type DuplicateReleaseError struct {
ID PermitID
}
DuplicateReleaseError identifies the permit released more than once.
func (*DuplicateReleaseError) Error ¶
func (err *DuplicateReleaseError) Error() string
Error returns a stable duplicate-release diagnostic.
func (*DuplicateReleaseError) Unwrap ¶
func (err *DuplicateReleaseError) Unwrap() error
Unwrap exposes ErrDuplicateRelease for errors.Is.
type EventKind ¶
type EventKind string
EventKind identifies one bounded semaphore state transition.
const ( // EventAdmitted reports successful acquisition. EventAdmitted EventKind = "admitted" // EventQueued reports entry into the bounded FIFO queue. EventQueued EventKind = "queued" // EventCanceled reports removal from the queue by caller cancellation. EventCanceled EventKind = "canceled" // EventRejected reports work that did not enter or acquire from the queue. EventRejected EventKind = "rejected" // EventReleased reports successful exactly-once permit release. EventReleased EventKind = "released" // EventClosed reports the first shutdown transition. EventClosed EventKind = "closed" )
type Observer ¶
type Observer interface {
Observe(Event)
}
Observer receives state transitions after accounting locks are released. Implementations must be safe for concurrent calls. Panics are recovered; slow callbacks delay only the caller delivering that event.
type ObserverFunc ¶
type ObserverFunc func(Event)
ObserverFunc adapts a function to Observer.
func (ObserverFunc) Observe ¶
func (observer ObserverFunc) Observe(event Event)
Observe calls observer(event).
type Permit ¶
type Permit struct {
// contains filtered or unexported fields
}
Permit owns acquired weight until Release succeeds exactly once.
type PermitID ¶
type PermitID uint64
PermitID is stable process-local identity metadata for one admission.
type QueueFullError ¶
type QueueFullError struct {
MaxWaiters int
}
QueueFullError reports deterministic bounded-waiter saturation.
func (*QueueFullError) Error ¶
func (err *QueueFullError) Error() string
Error returns a bounded saturation diagnostic.
func (*QueueFullError) Unwrap ¶
func (err *QueueFullError) Unwrap() error
Unwrap exposes ErrQueueFull for errors.Is.
type Reason ¶
type Reason string
Reason is a bounded, low-cardinality transition reason.
const ( // ReasonImmediate identifies acquisition without waiting. ReasonImmediate Reason = "immediate" // ReasonFIFO identifies admission from the FIFO queue. ReasonFIFO Reason = "fifo" ReasonUnavailable Reason = "unavailable" // ReasonInvalidWeight identifies a non-positive weight. ReasonInvalidWeight Reason = "invalid_weight" // ReasonOversize identifies a weight above total capacity. ReasonOversize Reason = "oversize" // ReasonQueueFull identifies bounded queue saturation. ReasonQueueFull Reason = "queue_full" // ReasonContextCanceled identifies caller cancellation. ReasonContextCanceled Reason = "context_canceled" // ReasonDeadline identifies caller deadline expiry. ReasonDeadline Reason = "deadline" // ReasonClosed identifies work rejected by shutdown. ReasonClosed Reason = "closed" // ReasonReleased identifies successful permit release. ReasonReleased Reason = "released" // ReasonShutdown identifies the first close operation. ReasonShutdown Reason = "shutdown" )
type Semaphore ¶
type Semaphore struct {
// contains filtered or unexported fields
}
Semaphore is a process-local weighted counting semaphore.
func (*Semaphore) Acquire ¶
Acquire acquires positive weight immediately when capacity is available or waits in strict FIFO order. The context must be non-nil.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/faustbrian/go-semaphore"
)
func main() {
sem, err := semaphore.New(semaphore.Config{Capacity: 3, MaxWaiters: 8})
if err != nil {
panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
permit, err := sem.Acquire(ctx, 2)
if err != nil {
panic(err)
}
defer func() {
if err := permit.Release(); err != nil {
panic(err)
}
}()
fmt.Println(permit.Weight(), sem.Snapshot().Available)
}
Output: 2 1
func (*Semaphore) Close ¶
Close idempotently stops new admission and rejects every queued waiter. Existing permits remain valid and releasable.
func (*Semaphore) Run ¶
func (semaphore *Semaphore) Run(ctx context.Context, weight int64, operation func(context.Context) error) error
Run is the error-only convenience form of Execute.
func (*Semaphore) TryAcquire ¶
TryAcquire attempts immediate admission without bypassing queued callers.
type Snapshot ¶
type Snapshot struct {
Capacity int64
Acquired int64
Available int64
Waiters int
Admissions uint64
Rejections uint64
Cancellations uint64
Closed bool
}
Snapshot is an immutable copy of observable semaphore state.
type WeightError ¶
WeightError describes an invalid or oversized acquisition request.
func (*WeightError) Error ¶
func (err *WeightError) Error() string
Error returns a bounded weight diagnostic.
func (*WeightError) Unwrap ¶
func (err *WeightError) Unwrap() error
Unwrap classifies the invalid weight for errors.Is.