powerlock

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, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

README

powerlock

This repository contains alternative lock implementations to help with debugging and monitoring Go applications.

  • CancelRWMutex - Cancellable locks that can reject all current and future waiters
  • MaxRWMutex - Locks that limit the number of waiting goroutines
  • ContextRWMutex - Locks that return when a context is cancelled or times out
  • ObservedRWMutex - Structured acquisition, release, contention, and rejection events
  • WatchdogRWMutex - Wait and hold threshold diagnostics with acquisition stacks
  • KeyedMutex - Independent exclusion by comparable key with bounded key counts

Overview

A Go library providing enhanced read-write mutex implementations with advanced features for monitoring, debugging, and resource management.

Example Powerlock Prometheus dashboard

See Choosing a lock for a side-by-side comparison of failure behavior, observation, and zero-value support.

Features

This library offers specialized read-write and exclusive mutex types for different concurrent programming challenges:

CancelRWMutex - Cancellable Locking

A read-write mutex that can be cancelled to reject all current and future lock attempts.

Key capabilities:

  • Cancellation support - Cancel() method rejects all waiters and future attempts
  • Lock() and RLock() panic when cancelled; try-methods return false
  • Non-blocking try-lock operations for both read and write locks
  • Compatible with standard sync.RWMutex interface

Usage:

import "github.com/donomii/powerlock"

mutex := powerlock.NewCancelRWMutex("database-access")

// Normal locking operations
mutex.Lock()
defer mutex.Unlock()
// Critical section

// Non-blocking operations
if mutex.TryLock() {
    defer mutex.Unlock()
    // Critical section
}

// Cancel the mutex to reject all current and future waiters
mutex.Cancel()
// After cancellation:
// - Lock() and RLock() will panic
// - TryLock() and TryRLock() will return false
MaxRWMutex - Limited Waiter Queue

A read-write mutex that limits the number of goroutines that can wait for the lock. Excess goroutines will be rejected immediately.

Key capabilities:

  • Configurable maximum number of waiting goroutines
  • Fails fast when wait limit is exceeded
  • Prevents system overload from unbounded lock queues

Usage:

mutex := powerlock.NewMaxRWMutexWithLimit("api-handler", 64)

// Will fail immediately if too many goroutines are already waiting
if mutex.TryLock() {
    defer mutex.Unlock()
    // Critical section
} else {
    // Handle the lock being unavailable without joining the queue.
}

NewMaxRWMutex(location) uses a default limit of 1.

ObservedRWMutex and WatchdogRWMutex - Diagnostics and Prometheus

Observed locks emit structured state transitions. Watchdog locks add configurable slow-wait and long-hold reports with acquisition stacks. The optional powerlock/prometheus adapter converts those events into bounded metrics without adding Prometheus imports to the core package.

Key capabilities:

  • Read/write waiter and holder gauges
  • Acquisition result and contention counters
  • Wait and exact-hold duration histograms
  • Wait and hold threshold counters
  • Cached metric handles for stable lock names
  • Runtime trace annotations with an optional application-owned flight-recorder callback

Usage:

import (
    powerlockprometheus "github.com/donomii/powerlock/prometheus"
    "github.com/prometheus/client_golang/prometheus"
)

reg := prometheus.NewRegistry()
metrics := powerlockprometheus.MustNew(reg)
mutex := metrics.NewWatchdogRWMutex("cache-update")

mutex.Lock()
defer mutex.Unlock()
// Structured events and Prometheus metrics are updated automatically.
ContextRWMutex - Context-Aware Locking

A read-write mutex whose blocking lock operations return if the supplied context is cancelled or reaches its deadline.

Key capabilities:

  • LockContext(ctx) and RLockContext(ctx) return typed acquisition errors that preserve ctx.Err() through errors.Is
  • Lock() and RLock() remain available for standard blocking use
  • Non-blocking try-lock operations for both read and write locks

Usage:

mutex := powerlock.NewContextRWMutex("request-state")

ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()

if err := mutex.LockContext(ctx); err != nil {
    // Handle timeout or cancellation
    return
}
defer mutex.Unlock()

Installation

go get github.com/donomii/powerlock@latest

Requirements

  • Go 1.23 or later
  • Prometheus client library only when importing the optional powerlock/prometheus adapter

Use Cases

  • CancelRWMutex: Graceful shutdown scenarios, resource cleanup, or any situation where you need to cancel pending operations
  • MaxRWMutex: High-throughput services where you want to prevent lock queue buildup
  • ContextRWMutex: Request-scoped work where waiting for a lock must respect cancellation and deadlines
  • ObservedRWMutex: Structured diagnostics, metrics adapters, and exact acquisition guards
  • WatchdogRWMutex: Slow-wait and long-hold incidents with acquisition callers
  • KeyedMutex: Per-customer, per-resource, or per-job exclusion without a permanent lock map

Common Interface

All read-write mutex types provide these methods:

  • Lock() / Unlock() - Exclusive write access
  • RLock() / RUnlock() - Shared read access
  • TryLock() / TryRLock() - Non-blocking lock attempts
  • SetLocation(string) - Set the stable diagnostic name before first use

Each type extends this base interface with its specialized capabilities:

  • CancelRWMutex adds: Cancel() method for rejecting waiters
  • MaxRWMutex adds: waiter limiting behavior
  • ContextRWMutex adds: LockContext(context.Context) and RLockContext(context.Context)
  • ObservedRWMutex adds: structured events and exact acquisition guards
  • WatchdogRWMutex adds: wait and exact-hold threshold reports

Exclusive-only forms omit the read methods. KeyedMutex accepts a key on acquisition and release.

Examples

go run ./examples/cancel
go run ./examples/max
go run ./examples/metrics
go run ./examples/context
go run ./examples/keyed
go run ./examples/watchdog

Benchmarks

go test -bench=.

License and notices

See LICENSE for Powerlock's license and THIRD_PARTY_NOTICES.md for retained upstream notices.

Documentation

Overview

Package powerlock provides named, context-aware, bounded, cancellable, observable, and watchdog mutexes.

The read/write lock types use FIFO waiter ordering. Context methods return typed errors whose causes remain available through errors.Is and errors.As. Blocking Lock methods retain sync.Locker behavior and panic when a specialized lock rejects an acquisition. Try methods never join or bypass an existing waiter queue.

Observed locks emit structured transition events. Watchdog locks add wait and exact-hold threshold events, while LockGuard permits exact pairing of individual reader acquisitions. DefaultProfileObserver exposes current waiters and exactly paired holders through runtime pprof profiles. RuntimeTraceObserver annotates watchdog thresholds in Go execution traces and can notify an application-owned flight recorder.

Use ContextRWMutex for cancellable FIFO waiting, CancelRWMutex for irreversible shutdown, MaxRWMutex to bound blocked acquisitions, ObservedRWMutex for complete event and metric reporting, WatchdogRWMutex for slow wait and hold diagnostics, and KeyedMutex to serialize work independently by key. Exclusive forms omit the read methods. LockEvent.String formats an event as a single actionable diagnostic line. Prefer sync.Mutex or sync.RWMutex when these controls and diagnostics are not needed.

Index

Examples

Constants

View Source
const (
	// DefaultWaitThreshold reports acquisitions that wait for at least one second.
	DefaultWaitThreshold = time.Second
	// DefaultHoldThreshold reports exact acquisitions that remain held for at least five seconds.
	DefaultHoldThreshold = 5 * time.Second
)
View Source
const DefaultMaxKeys = 1024

DefaultMaxKeys is the maximum number of active keyed lock entries used by the zero value and NewKeyedMutex.

View Source
const DefaultMaxWaiting = 1

DefaultMaxWaiting is the waiter limit used by NewMaxRWMutex and the zero value.

Variables

View Source
var (
	// ErrBusy identifies an acquisition that could not proceed immediately.
	ErrBusy = errors.New("powerlock: lock is busy")
	// ErrCancelled identifies an acquisition rejected by context or permanent lock cancellation.
	ErrCancelled = errors.New("powerlock: lock was cancelled")
	// ErrMaxKeys identifies an acquisition rejected by a KeyedMutex active-key limit.
	ErrMaxKeys = errors.New("powerlock: maximum keyed locks reached")
	// ErrMaxWaiting identifies an acquisition rejected by a MaxRWMutex waiter limit.
	ErrMaxWaiting = errors.New("powerlock: maximum waiting acquisitions reached")
	// ErrInvalidConfig identifies an invalid constructor value or forbidden post-use reconfiguration.
	ErrInvalidConfig = errors.New("powerlock: invalid configuration")
)

Functions

This section is empty.

Types

type AcquisitionError

type AcquisitionError struct {
	Name       string
	Mode       LockMode
	Result     LockResult
	MaxWaiting int
	State      LockState
	Cause      error
}

AcquisitionError reports why a lock acquisition did not complete.

func (*AcquisitionError) Error

func (e *AcquisitionError) Error() string

Error returns the complete acquisition failure.

func (*AcquisitionError) Unwrap

func (e *AcquisitionError) Unwrap() error

Unwrap returns the underlying acquisition failure.

type CancelMutex

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

CancelMutex is the exclusive-only form of CancelRWMutex.

func NewCancelMutex

func NewCancelMutex(name string) *CancelMutex

NewCancelMutex returns a cancellable exclusive lock.

func (*CancelMutex) Cancel

func (m *CancelMutex) Cancel()

Cancel permanently rejects queued and future acquisitions.

func (*CancelMutex) Cancelled

func (m *CancelMutex) Cancelled() bool

Cancelled reports whether Cancel has been called.

func (*CancelMutex) Lock

func (m *CancelMutex) Lock()

Lock acquires the mutex and panics after cancellation.

func (*CancelMutex) LockContext

func (m *CancelMutex) LockContext(ctx context.Context) error

LockContext acquires the mutex or returns a cancellation or deadline error.

func (*CancelMutex) Name

func (m *CancelMutex) Name() string

Name returns the immutable diagnostic name.

func (*CancelMutex) SetLocation

func (m *CancelMutex) SetLocation(name string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*CancelMutex) Snapshot

func (m *CancelMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*CancelMutex) TryLock

func (m *CancelMutex) TryLock() bool

TryLock attempts to acquire the mutex without waiting.

func (*CancelMutex) Unlock

func (m *CancelMutex) Unlock()

Unlock releases the mutex.

type CancelRWMutex

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

CancelRWMutex is a FIFO read/write lock that permanently rejects acquisitions after cancellation.

func NewCancelRWMutex

func NewCancelRWMutex(location string) *CancelRWMutex

NewCancelRWMutex returns a cancellable lock with the supplied diagnostic name.

func (*CancelRWMutex) Cancel

func (m *CancelRWMutex) Cancel()

Cancel permanently rejects queued and future acquisitions while allowing current holders to unlock.

func (*CancelRWMutex) Cancelled

func (m *CancelRWMutex) Cancelled() bool

Cancelled reports whether Cancel has been called.

func (*CancelRWMutex) Lock

func (m *CancelRWMutex) Lock()

Lock acquires the write lock and panics if the lock has been cancelled.

func (*CancelRWMutex) LockContext

func (m *CancelRWMutex) LockContext(ctx context.Context) error

LockContext acquires the write lock or returns a cancellation or deadline error.

func (*CancelRWMutex) Name

func (m *CancelRWMutex) Name() string

Name returns the immutable diagnostic name.

func (*CancelRWMutex) RLock

func (m *CancelRWMutex) RLock()

RLock acquires the read lock and panics if the lock has been cancelled.

func (*CancelRWMutex) RLockContext

func (m *CancelRWMutex) RLockContext(ctx context.Context) error

RLockContext acquires the read lock or returns a cancellation or deadline error.

func (*CancelRWMutex) RLocker

func (m *CancelRWMutex) RLocker() sync.Locker

RLocker returns a sync.Locker backed by RLock and RUnlock.

func (*CancelRWMutex) RUnlock

func (m *CancelRWMutex) RUnlock()

RUnlock releases one read lock.

func (*CancelRWMutex) SetLocation

func (m *CancelRWMutex) SetLocation(location string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*CancelRWMutex) Snapshot

func (m *CancelRWMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*CancelRWMutex) TryLock

func (m *CancelRWMutex) TryLock() bool

TryLock attempts to acquire the write lock without waiting.

func (*CancelRWMutex) TryRLock

func (m *CancelRWMutex) TryRLock() bool

TryRLock attempts to acquire a read lock without waiting or bypassing queued acquisitions.

func (*CancelRWMutex) Unlock

func (m *CancelRWMutex) Unlock()

Unlock releases the write lock.

type ContextMutex

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

ContextMutex is the exclusive-only form of ContextRWMutex.

func NewContextMutex

func NewContextMutex(name string) *ContextMutex

NewContextMutex returns a FIFO context-aware exclusive lock.

func (*ContextMutex) Lock

func (m *ContextMutex) Lock()

Lock acquires the mutex.

func (*ContextMutex) LockContext

func (m *ContextMutex) LockContext(ctx context.Context) error

LockContext acquires the mutex or returns a cancellation or deadline error.

func (*ContextMutex) Name

func (m *ContextMutex) Name() string

Name returns the immutable diagnostic name.

func (*ContextMutex) SetLocation

func (m *ContextMutex) SetLocation(name string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*ContextMutex) Snapshot

func (m *ContextMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*ContextMutex) TryLock

func (m *ContextMutex) TryLock() bool

TryLock attempts to acquire the mutex without waiting.

func (*ContextMutex) Unlock

func (m *ContextMutex) Unlock()

Unlock releases the mutex.

type ContextRWMutex

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

ContextRWMutex is a FIFO read/write lock whose queued acquisitions can be cancelled.

Example
package main

import (
	"fmt"

	"github.com/donomii/powerlock"
)

func main() {
	lock := powerlock.NewContextRWMutex("cache")
	lock.Lock()
	fmt.Printf("name=%s writer=%t\n", lock.Name(), lock.Snapshot().Writer)
	lock.Unlock()
}
Output:
name=cache writer=true

func NewContextRWMutex

func NewContextRWMutex(location string) *ContextRWMutex

NewContextRWMutex returns a context-aware lock with the supplied diagnostic name.

func (*ContextRWMutex) Lock

func (m *ContextRWMutex) Lock()

Lock acquires the write lock.

func (*ContextRWMutex) LockContext

func (m *ContextRWMutex) LockContext(ctx context.Context) error

LockContext acquires the write lock or returns a cancellation or deadline error.

func (*ContextRWMutex) Name

func (m *ContextRWMutex) Name() string

Name returns the immutable diagnostic name.

func (*ContextRWMutex) RLock

func (m *ContextRWMutex) RLock()

RLock acquires a read lock.

func (*ContextRWMutex) RLockContext

func (m *ContextRWMutex) RLockContext(ctx context.Context) error

RLockContext acquires a read lock or returns a cancellation or deadline error.

func (*ContextRWMutex) RLocker

func (m *ContextRWMutex) RLocker() sync.Locker

RLocker returns a sync.Locker backed by RLock and RUnlock.

func (*ContextRWMutex) RUnlock

func (m *ContextRWMutex) RUnlock()

RUnlock releases one read lock.

func (*ContextRWMutex) SetLocation

func (m *ContextRWMutex) SetLocation(location string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*ContextRWMutex) Snapshot

func (m *ContextRWMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*ContextRWMutex) TryLock

func (m *ContextRWMutex) TryLock() bool

TryLock attempts to acquire the write lock without waiting.

func (*ContextRWMutex) TryRLock

func (m *ContextRWMutex) TryRLock() bool

TryRLock attempts to acquire a read lock without waiting or bypassing queued acquisitions.

func (*ContextRWMutex) Unlock

func (m *ContextRWMutex) Unlock()

Unlock releases the write lock.

type FairMutex

type FairMutex = ContextMutex

FairMutex is the explicitly named FIFO form of ContextMutex.

func NewFairMutex

func NewFairMutex(name string) *FairMutex

NewFairMutex returns a FIFO context-aware exclusive lock.

type FairRWMutex

type FairRWMutex = ContextRWMutex

FairRWMutex is the explicitly named FIFO form of ContextRWMutex.

func NewFairRWMutex

func NewFairRWMutex(name string) *FairRWMutex

NewFairRWMutex returns a FIFO context-aware read/write lock.

type FlightRecorderCallback

type FlightRecorderCallback func(LockEvent)

FlightRecorderCallback receives watchdog threshold events after their runtime trace annotation is written. Applications using Go 1.25 or later can use it to enqueue a snapshot of an active runtime trace flight recorder.

type KeyGuard

type KeyGuard[K comparable] struct {
	// contains filtered or unexported fields
}

KeyGuard owns one keyed acquisition and releases it once.

func (*KeyGuard[K]) AttemptID

func (g *KeyGuard[K]) AttemptID() LockAttemptID

AttemptID returns the diagnostic identifier for the keyed acquisition.

func (*KeyGuard[K]) Key

func (g *KeyGuard[K]) Key() K

Key returns the key owned by the guard.

func (*KeyGuard[K]) Released

func (g *KeyGuard[K]) Released() bool

Released reports whether Unlock has already released the keyed acquisition.

func (*KeyGuard[K]) Unlock

func (g *KeyGuard[K]) Unlock()

Unlock releases the keyed acquisition and panics if it has already been released.

type KeyedAcquisitionError

type KeyedAcquisitionError[K comparable] struct {
	Name       string
	Key        K
	MaxKeys    int
	ActiveKeys int
	Cause      error
}

KeyedAcquisitionError reports a keyed-lock failure with its capacity state.

func (*KeyedAcquisitionError[K]) Error

func (e *KeyedAcquisitionError[K]) Error() string

Error returns the complete keyed acquisition failure.

func (*KeyedAcquisitionError[K]) Unwrap

func (e *KeyedAcquisitionError[K]) Unwrap() error

Unwrap returns the underlying keyed acquisition failure.

type KeyedMutex

type KeyedMutex[K comparable] struct {
	// contains filtered or unexported fields
}

KeyedMutex serializes work by comparable key and removes entries after their last holder or waiter exits.

func NewKeyedMutex

func NewKeyedMutex[K comparable](name string) *KeyedMutex[K]

NewKeyedMutex returns a keyed lock using DefaultMaxKeys.

func NewKeyedMutexWithLimit

func NewKeyedMutexWithLimit[K comparable](name string, maxKeys int) *KeyedMutex[K]

NewKeyedMutexWithLimit returns a keyed lock with a maximum count of referenced keys.

func (*KeyedMutex[K]) ActiveKeys

func (m *KeyedMutex[K]) ActiveKeys() int

ActiveKeys returns the number of keys currently held or awaited.

func (*KeyedMutex[K]) Lock

func (m *KeyedMutex[K]) Lock(key K)

Lock acquires the lock for key and panics when the active-key limit has been reached.

func (*KeyedMutex[K]) LockContext

func (m *KeyedMutex[K]) LockContext(ctx context.Context, key K) error

LockContext acquires the lock for key or returns a context or active-key-capacity error.

func (*KeyedMutex[K]) LockGuard

func (m *KeyedMutex[K]) LockGuard(ctx context.Context, key K) (*KeyGuard[K], error)

LockGuard acquires key and returns an exact release token.

func (*KeyedMutex[K]) MaxKeys

func (m *KeyedMutex[K]) MaxKeys() int

MaxKeys returns the configured active-key limit.

func (*KeyedMutex[K]) Name

func (m *KeyedMutex[K]) Name() string

Name returns the immutable diagnostic name.

func (*KeyedMutex[K]) SetLocation

func (m *KeyedMutex[K]) SetLocation(name string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*KeyedMutex[K]) Snapshot

func (m *KeyedMutex[K]) Snapshot(key K) (LockState, bool)

Snapshot returns the state for key and reports whether the key is referenced.

func (*KeyedMutex[K]) TryLock

func (m *KeyedMutex[K]) TryLock(key K) bool

TryLock attempts to acquire key without waiting or retaining a failed entry reference.

func (*KeyedMutex[K]) Unlock

func (m *KeyedMutex[K]) Unlock(key K)

Unlock releases the lock for key.

type LockAttemptID

type LockAttemptID uint64

LockAttemptID uniquely identifies one acquisition attempt within the process.

type LockEvent

type LockEvent struct {
	Name              string
	Mode              LockMode
	Kind              LockEventKind
	Result            LockResult
	AttemptID         LockAttemptID
	Contended         bool
	WaitDuration      time.Duration
	HoldDuration      time.Duration
	HoldDurationKnown bool
	ExactHold         bool
	Callers           []uintptr
	State             LockState
}

LockEvent describes one acquisition or release transition. Observers must treat the value and Callers slice as read-only.

Example
package main

import (
	"fmt"
	"time"

	"github.com/donomii/powerlock"
)

func main() {
	event := powerlock.LockEvent{
		Name:         "cache",
		Mode:         powerlock.LockModeWrite,
		Kind:         powerlock.LockEventWaitExceeded,
		Result:       powerlock.LockResultBusy,
		Contended:    true,
		WaitDuration: 2 * time.Second,
		State: powerlock.LockState{
			Name:           "cache",
			Readers:        1,
			WaitingWriters: 1,
		},
	}
	fmt.Println(event)
}
Output:
powerlock event=wait_exceeded lock="cache" mode=write result=busy contended=true wait=2s hold=unmeasured readers=1 writer=false waiting_readers=0 waiting_writers=1 cancelled=false caller=unavailable

func (LockEvent) Caller

func (e LockEvent) Caller() string

Caller returns the first captured frame outside Powerlock, or "unavailable" when no such frame exists.

func (LockEvent) String

func (e LockEvent) String() string

String returns an actionable single-line diagnostic containing timing, ownership, queue state, and caller.

type LockEventKind

type LockEventKind uint8

LockEventKind identifies a lock state transition reported to an observer.

const (
	// LockEventWaitStarted reports that an acquisition joined the waiter queue.
	LockEventWaitStarted LockEventKind = iota + 1
	// LockEventWaitExceeded reports that a queued acquisition crossed its wait threshold.
	LockEventWaitExceeded
	// LockEventAcquired reports that ownership was granted.
	LockEventAcquired
	// LockEventReleased reports that ownership was released.
	LockEventReleased
	// LockEventTryFailed reports that a non-blocking acquisition did not acquire ownership.
	LockEventTryFailed
	// LockEventRejected reports that cancellation, expiry, or capacity ended an acquisition.
	LockEventRejected
	// LockEventHoldExceeded reports that an exact acquisition crossed its hold threshold.
	LockEventHoldExceeded
)

func (LockEventKind) String

func (k LockEventKind) String() string

String returns the diagnostic name for a lock event kind.

type LockGuard

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

LockGuard owns one exact acquisition and releases it once.

func (*LockGuard) AttemptID

func (g *LockGuard) AttemptID() LockAttemptID

AttemptID returns the diagnostic identifier for the acquisition.

func (*LockGuard) Mode

func (g *LockGuard) Mode() LockMode

Mode reports whether the guard owns a read or write acquisition.

func (*LockGuard) Released

func (g *LockGuard) Released() bool

Released reports whether Unlock has already released the acquisition.

func (*LockGuard) Unlock

func (g *LockGuard) Unlock()

Unlock releases the acquisition and panics if the guard has already been released.

type LockMode

type LockMode uint8

LockMode identifies whether an acquisition is exclusive or shared.

const (
	// LockModeWrite identifies an exclusive acquisition.
	LockModeWrite LockMode = iota + 1
	// LockModeRead identifies a shared acquisition.
	LockModeRead
)

func (LockMode) String

func (m LockMode) String() string

String returns the diagnostic name for a lock mode.

type LockObserver

type LockObserver interface {
	ObserveLock(LockEvent)
}

LockObserver receives ordered lock events. Calls may be concurrent across acquisitions, so implementations must be concurrency-safe, return promptly, not panic, and not acquire or release the lock emitting the event.

type LockObserverFunc

type LockObserverFunc func(LockEvent)

LockObserverFunc adapts a function to LockObserver.

func (LockObserverFunc) ObserveLock

func (f LockObserverFunc) ObserveLock(event LockEvent)

ObserveLock calls the observer function.

type LockObserverGroup

type LockObserverGroup []LockObserver

LockObserverGroup delivers each event to its observers in order and must not be mutated while in use.

func (LockObserverGroup) ObserveLock

func (g LockObserverGroup) ObserveLock(event LockEvent)

ObserveLock delivers event to each non-nil observer.

type LockResult

type LockResult uint8

LockResult identifies the result of an acquisition attempt.

const (
	// LockResultAcquired means ownership was granted.
	LockResultAcquired LockResult = iota + 1
	// LockResultBusy means a non-blocking acquisition found incompatible ownership or an earlier waiter.
	LockResultBusy
	// LockResultQueueFull means a bounded waiter queue had no remaining capacity.
	LockResultQueueFull
	// LockResultCancelled means a context or permanently cancellable lock was cancelled.
	LockResultCancelled
	// LockResultDeadlineExceeded means the acquisition context expired before ownership was granted.
	LockResultDeadlineExceeded
)

func (LockResult) String

func (r LockResult) String() string

String returns the metric and diagnostic name for an acquisition result.

type LockState

type LockState struct {
	Name                     string
	Version                  uint64
	Readers                  int
	Writer                   bool
	WaitingReaders           int
	WaitingWriters           int
	Cancelled                bool
	OldestWaitDuration       time.Duration
	WriterHoldDuration       time.Duration
	ReaderCohortHoldDuration time.Duration
}

LockState is a point-in-time view of a lock.

type MaxMutex

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

MaxMutex is the exclusive-only form of MaxRWMutex.

func NewMaxMutex

func NewMaxMutex(name string) *MaxMutex

NewMaxMutex returns a bounded exclusive lock using DefaultMaxWaiting.

func NewMaxMutexWithLimit

func NewMaxMutexWithLimit(name string, maxWaiting int) *MaxMutex

NewMaxMutexWithLimit returns a bounded exclusive lock with the supplied waiter limit.

func (*MaxMutex) Lock

func (m *MaxMutex) Lock()

Lock acquires the mutex and panics when the waiter limit has already been reached.

func (*MaxMutex) LockContext

func (m *MaxMutex) LockContext(ctx context.Context) error

LockContext acquires the mutex or returns a context or queue-saturation error.

func (*MaxMutex) MaxWaiting

func (m *MaxMutex) MaxWaiting() int

MaxWaiting returns the configured waiter limit.

func (*MaxMutex) Name

func (m *MaxMutex) Name() string

Name returns the immutable diagnostic name.

func (*MaxMutex) SetLocation

func (m *MaxMutex) SetLocation(name string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*MaxMutex) Snapshot

func (m *MaxMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*MaxMutex) TryLock

func (m *MaxMutex) TryLock() bool

TryLock attempts to acquire the mutex without joining the waiter queue.

func (*MaxMutex) Unlock

func (m *MaxMutex) Unlock()

Unlock releases the mutex.

type MaxRWMutex

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

MaxRWMutex is a FIFO read/write mutex that limits blocked acquisitions without limiting current holders.

func NewMaxRWMutex

func NewMaxRWMutex(location string) *MaxRWMutex

NewMaxRWMutex returns a bounded lock using DefaultMaxWaiting.

func NewMaxRWMutexWithLimit

func NewMaxRWMutexWithLimit(location string, maxWaiting int) *MaxRWMutex

NewMaxRWMutexWithLimit returns a bounded lock that permits at most maxWaiting blocked acquisitions.

func (*MaxRWMutex) Lock

func (m *MaxRWMutex) Lock()

Lock acquires the write lock and panics when the waiter limit has already been reached.

func (*MaxRWMutex) LockContext

func (m *MaxRWMutex) LockContext(ctx context.Context) error

LockContext acquires the write lock or returns a context or queue-saturation error.

func (*MaxRWMutex) MaxWaiting

func (m *MaxRWMutex) MaxWaiting() int

MaxWaiting returns the configured waiter limit.

func (*MaxRWMutex) Name

func (m *MaxRWMutex) Name() string

Name returns the immutable diagnostic name.

func (*MaxRWMutex) RLock

func (m *MaxRWMutex) RLock()

RLock acquires a read lock and panics when the waiter limit has already been reached.

func (*MaxRWMutex) RLockContext

func (m *MaxRWMutex) RLockContext(ctx context.Context) error

RLockContext acquires a read lock or returns a context or queue-saturation error.

func (*MaxRWMutex) RLocker

func (m *MaxRWMutex) RLocker() sync.Locker

RLocker returns a sync.Locker backed by RLock and RUnlock.

func (*MaxRWMutex) RUnlock

func (m *MaxRWMutex) RUnlock()

RUnlock releases one read lock.

func (*MaxRWMutex) SetLocation

func (m *MaxRWMutex) SetLocation(location string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*MaxRWMutex) Snapshot

func (m *MaxRWMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*MaxRWMutex) TryLock

func (m *MaxRWMutex) TryLock() bool

TryLock attempts to acquire the write lock without joining the waiter queue.

func (*MaxRWMutex) TryRLock

func (m *MaxRWMutex) TryRLock() bool

TryRLock attempts to acquire a read lock without joining or bypassing the waiter queue.

func (*MaxRWMutex) Unlock

func (m *MaxRWMutex) Unlock()

Unlock releases the write lock.

type ObservedMutex

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

ObservedMutex is the exclusive-only form of ObservedRWMutex.

func NewObservedMutex

func NewObservedMutex(name string, observer LockObserver) *ObservedMutex

NewObservedMutex returns an exclusive lock that emits structured events.

func (*ObservedMutex) Lock

func (m *ObservedMutex) Lock()

Lock acquires the mutex.

func (*ObservedMutex) LockContext

func (m *ObservedMutex) LockContext(ctx context.Context) error

LockContext acquires the mutex or returns a cancellation or deadline error.

func (*ObservedMutex) LockGuard

func (m *ObservedMutex) LockGuard(ctx context.Context) (*LockGuard, error)

LockGuard returns an exact acquisition guard.

func (*ObservedMutex) Name

func (m *ObservedMutex) Name() string

Name returns the immutable diagnostic name.

func (*ObservedMutex) SetLocation

func (m *ObservedMutex) SetLocation(name string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*ObservedMutex) Snapshot

func (m *ObservedMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*ObservedMutex) TryLock

func (m *ObservedMutex) TryLock() bool

TryLock attempts to acquire the mutex without waiting.

func (*ObservedMutex) TryLockGuard

func (m *ObservedMutex) TryLockGuard() (*LockGuard, bool)

TryLockGuard attempts to acquire the mutex and returns an exact release token on success.

func (*ObservedMutex) Unlock

func (m *ObservedMutex) Unlock()

Unlock releases the mutex.

type ObservedRWMutex

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

ObservedRWMutex is a FIFO context-aware read/write lock that emits structured events.

func NewObservedRWMutex

func NewObservedRWMutex(name string, observer LockObserver) *ObservedRWMutex

NewObservedRWMutex returns an observed lock. A nil observer disables event delivery.

func (*ObservedRWMutex) Lock

func (m *ObservedRWMutex) Lock()

Lock acquires the write lock.

func (*ObservedRWMutex) LockContext

func (m *ObservedRWMutex) LockContext(ctx context.Context) error

LockContext acquires the write lock or returns a cancellation or deadline error.

func (*ObservedRWMutex) LockGuard

func (m *ObservedRWMutex) LockGuard(ctx context.Context) (*LockGuard, error)

LockGuard acquires the write lock and returns an exact release token.

func (*ObservedRWMutex) Name

func (m *ObservedRWMutex) Name() string

Name returns the immutable diagnostic name.

func (*ObservedRWMutex) RLock

func (m *ObservedRWMutex) RLock()

RLock acquires a read lock.

func (*ObservedRWMutex) RLockContext

func (m *ObservedRWMutex) RLockContext(ctx context.Context) error

RLockContext acquires a read lock or returns a cancellation or deadline error.

func (*ObservedRWMutex) RLockGuard

func (m *ObservedRWMutex) RLockGuard(ctx context.Context) (*LockGuard, error)

RLockGuard acquires a read lock and returns an exact release token.

func (*ObservedRWMutex) RLocker

func (m *ObservedRWMutex) RLocker() sync.Locker

RLocker returns a sync.Locker backed by RLock and RUnlock.

func (*ObservedRWMutex) RUnlock

func (m *ObservedRWMutex) RUnlock()

RUnlock releases one read lock.

func (*ObservedRWMutex) SetLocation

func (m *ObservedRWMutex) SetLocation(location string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*ObservedRWMutex) Snapshot

func (m *ObservedRWMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*ObservedRWMutex) TryLock

func (m *ObservedRWMutex) TryLock() bool

TryLock attempts to acquire the write lock without waiting.

func (*ObservedRWMutex) TryLockGuard

func (m *ObservedRWMutex) TryLockGuard() (*LockGuard, bool)

TryLockGuard attempts to acquire the write lock and returns an exact release token on success.

func (*ObservedRWMutex) TryRLock

func (m *ObservedRWMutex) TryRLock() bool

TryRLock attempts to acquire a read lock without waiting or bypassing queued acquisitions.

func (*ObservedRWMutex) TryRLockGuard

func (m *ObservedRWMutex) TryRLockGuard() (*LockGuard, bool)

TryRLockGuard attempts to acquire a read lock and returns an exact release token on success.

func (*ObservedRWMutex) Unlock

func (m *ObservedRWMutex) Unlock()

Unlock releases the write lock.

type ProfileObserver

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

ProfileObserver exposes current waiters and exactly paired holders through runtime pprof profiles.

func DefaultProfileObserver

func DefaultProfileObserver() *ProfileObserver

DefaultProfileObserver returns the process-wide Powerlock pprof observer.

func (*ProfileObserver) HolderCount

func (o *ProfileObserver) HolderCount() int

HolderCount returns the number of acquisitions currently represented in the holder profile.

func (*ProfileObserver) HolderProfileName

func (o *ProfileObserver) HolderProfileName() string

HolderProfileName returns the pprof profile containing exactly paired current holders.

func (*ProfileObserver) ObserveLock

func (o *ProfileObserver) ObserveLock(event LockEvent)

ObserveLock updates the current waiter and exactly paired holder profiles.

func (*ProfileObserver) WaiterCount

func (o *ProfileObserver) WaiterCount() int

WaiterCount returns the number of acquisitions currently represented in the waiter profile.

func (*ProfileObserver) WaiterProfileName

func (o *ProfileObserver) WaiterProfileName() string

WaiterProfileName returns the pprof profile containing current waiters.

type RuntimeTraceObserver

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

RuntimeTraceObserver writes watchdog threshold events to the Go execution trace.

func NewRuntimeTraceObserver

func NewRuntimeTraceObserver(onThreshold FlightRecorderCallback) *RuntimeTraceObserver

NewRuntimeTraceObserver returns a runtime trace observer with an optional flight-recorder callback.

func (*RuntimeTraceObserver) ObserveLock

func (o *RuntimeTraceObserver) ObserveLock(event LockEvent)

ObserveLock records wait and hold threshold events under the powerlock trace category.

type WatchdogMutex

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

WatchdogMutex is the exclusive-only form of WatchdogRWMutex.

func NewWatchdogMutex

func NewWatchdogMutex(name string, observer LockObserver) *WatchdogMutex

NewWatchdogMutex returns an exclusive watchdog lock with the default thresholds.

func NewWatchdogMutexWithThresholds

func NewWatchdogMutexWithThresholds(name string, waitThreshold time.Duration, holdThreshold time.Duration, observer LockObserver) *WatchdogMutex

NewWatchdogMutexWithThresholds returns an exclusive watchdog lock with explicit thresholds. Zero disables that threshold.

func (*WatchdogMutex) HoldThreshold

func (m *WatchdogMutex) HoldThreshold() time.Duration

HoldThreshold returns the duration after which an exact active acquisition is reported.

func (*WatchdogMutex) Lock

func (m *WatchdogMutex) Lock()

Lock acquires the mutex.

func (*WatchdogMutex) LockContext

func (m *WatchdogMutex) LockContext(ctx context.Context) error

LockContext acquires the mutex or returns a cancellation or deadline error.

func (*WatchdogMutex) LockGuard

func (m *WatchdogMutex) LockGuard(ctx context.Context) (*LockGuard, error)

LockGuard returns an exact acquisition guard.

func (*WatchdogMutex) Name

func (m *WatchdogMutex) Name() string

Name returns the immutable diagnostic name.

func (*WatchdogMutex) SetLocation

func (m *WatchdogMutex) SetLocation(name string)

SetLocation changes the diagnostic name before the first operation and panics after first use.

func (*WatchdogMutex) Snapshot

func (m *WatchdogMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*WatchdogMutex) TryLock

func (m *WatchdogMutex) TryLock() bool

TryLock attempts to acquire the mutex without waiting.

func (*WatchdogMutex) TryLockGuard

func (m *WatchdogMutex) TryLockGuard() (*LockGuard, bool)

TryLockGuard attempts to acquire the mutex and returns an exact release token on success.

func (*WatchdogMutex) Unlock

func (m *WatchdogMutex) Unlock()

Unlock releases the mutex.

func (*WatchdogMutex) WaitThreshold

func (m *WatchdogMutex) WaitThreshold() time.Duration

WaitThreshold returns the duration after which a queued acquisition is reported.

type WatchdogRWMutex

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

WatchdogRWMutex reports slow waits and long exact holds while providing FIFO context-aware locking.

func NewWatchdogRWMutex

func NewWatchdogRWMutex(name string, observer LockObserver) *WatchdogRWMutex

NewWatchdogRWMutex returns a watchdog lock with the default wait and hold thresholds.

func NewWatchdogRWMutexWithThresholds

func NewWatchdogRWMutexWithThresholds(name string, waitThreshold time.Duration, holdThreshold time.Duration, observer LockObserver) *WatchdogRWMutex

NewWatchdogRWMutexWithThresholds returns a watchdog lock with explicit thresholds. Zero disables that threshold.

func (*WatchdogRWMutex) HoldThreshold

func (m *WatchdogRWMutex) HoldThreshold() time.Duration

HoldThreshold returns the duration after which an exact active acquisition is reported.

func (*WatchdogRWMutex) Lock

func (m *WatchdogRWMutex) Lock()

Lock acquires the write lock.

func (*WatchdogRWMutex) LockContext

func (m *WatchdogRWMutex) LockContext(ctx context.Context) error

LockContext acquires the write lock or returns a cancellation or deadline error.

func (*WatchdogRWMutex) LockGuard

func (m *WatchdogRWMutex) LockGuard(ctx context.Context) (*LockGuard, error)

LockGuard acquires the write lock and returns an exact release token.

func (*WatchdogRWMutex) Name

func (m *WatchdogRWMutex) Name() string

Name returns the immutable diagnostic name.

func (*WatchdogRWMutex) RLock

func (m *WatchdogRWMutex) RLock()

RLock acquires a read lock.

func (*WatchdogRWMutex) RLockContext

func (m *WatchdogRWMutex) RLockContext(ctx context.Context) error

RLockContext acquires a read lock or returns a cancellation or deadline error.

func (*WatchdogRWMutex) RLockGuard

func (m *WatchdogRWMutex) RLockGuard(ctx context.Context) (*LockGuard, error)

RLockGuard acquires a read lock and returns an exact release token.

func (*WatchdogRWMutex) RLocker

func (m *WatchdogRWMutex) RLocker() sync.Locker

RLocker returns a sync.Locker backed by RLock and RUnlock.

func (*WatchdogRWMutex) RUnlock

func (m *WatchdogRWMutex) RUnlock()

RUnlock releases one read lock.

func (*WatchdogRWMutex) SetLocation

func (m *WatchdogRWMutex) SetLocation(name string)

SetLocation changes the non-empty diagnostic name before the first operation and panics after first use.

func (*WatchdogRWMutex) Snapshot

func (m *WatchdogRWMutex) Snapshot() LockState

Snapshot returns the current lock state.

func (*WatchdogRWMutex) TryLock

func (m *WatchdogRWMutex) TryLock() bool

TryLock attempts to acquire the write lock without waiting.

func (*WatchdogRWMutex) TryLockGuard

func (m *WatchdogRWMutex) TryLockGuard() (*LockGuard, bool)

TryLockGuard attempts to acquire the write lock and returns an exact release token on success.

func (*WatchdogRWMutex) TryRLock

func (m *WatchdogRWMutex) TryRLock() bool

TryRLock attempts to acquire a read lock without waiting or bypassing queued acquisitions.

func (*WatchdogRWMutex) TryRLockGuard

func (m *WatchdogRWMutex) TryRLockGuard() (*LockGuard, bool)

TryRLockGuard attempts to acquire a read lock and returns an exact release token on success.

func (*WatchdogRWMutex) Unlock

func (m *WatchdogRWMutex) Unlock()

Unlock releases the write lock.

func (*WatchdogRWMutex) WaitThreshold

func (m *WatchdogRWMutex) WaitThreshold() time.Duration

WaitThreshold returns the duration after which a queued acquisition is reported.

Directories

Path Synopsis
cmd
checkfmt command
examples
cancel command
context command
keyed command
max command
metrics command
watchdog command
Package powerlockprometheus converts Powerlock's structured lock events into bounded Prometheus metrics.
Package powerlockprometheus converts Powerlock's structured lock events into bounded Prometheus metrics.

Jump to

Keyboard shortcuts

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