Documentation
¶
Overview ¶
Package manual provides fixed timestamps and explicitly advanced test clocks. NewFixed is an immutable wall-time seam; New constructs a concurrency-safe Clock whose elapsed progress is independent of Jump's wall-time corrections. The package does not replace process time or automatically advance blocked goroutines, and it requires no cgo or external service.
Clock owns bounded schedules and advancement waiters. Call Close to release scheduled work. Advancements may start callback goroutines and wait for them; callbacks must cooperate and use a nested advancement waiter to permit future progress. Closing the clock does not wait for running callbacks.
Index ¶
- Variables
- type Callback
- type Clock
- func (clock *Clock) Advance(duration time.Duration) (*Waiter, error)
- func (clock *Clock) AdvanceTo(target time.Time) (*Waiter, error)
- func (clock *Clock) AfterFunc(duration time.Duration, function func()) (clockpkg.Callback, error)
- func (clock *Clock) Close() error
- func (clock *Clock) Jump(delta time.Duration) error
- func (clock *Clock) Mark() time.Duration
- func (clock *Clock) Measure() func() time.Duration
- func (clock *Clock) NewTicker(duration time.Duration) (clockpkg.Ticker, error)
- func (clock *Clock) NewTimer(duration time.Duration) (clockpkg.Timer, error)
- func (clock *Clock) Now() time.Time
- func (clock *Clock) Shutdown() errordeprecated
- func (clock *Clock) Since(start time.Time) time.Duration
- func (clock *Clock) SinceMark(mark time.Duration) time.Duration
- func (clock *Clock) Sleep(ctx context.Context, duration time.Duration) error
- func (clock *Clock) Snapshot() Snapshot
- type Fixed
- type Limits
- type Option
- type Result
- type Snapshot
- type Ticker
- type Timer
- type Waiter
Constants ¶
This section is empty.
Variables ¶
var ( // ErrActiveLimit reports exhaustion of the scheduled-object or waiter budget. ErrActiveLimit = errors.New("manual clock: active object limit exceeded") // ErrWorkLimit reports exhaustion of a coordinator run's shared event budget. ErrWorkLimit = errors.New("manual clock: advancement work limit exceeded") // ErrClosed reports an operation attempted after the clock is closed. ErrClosed = errors.New("manual clock: closed") // ErrBackwardAdvance reports an AdvanceTo target before the current wall time. ErrBackwardAdvance = errors.New("manual clock: backward advance") // ErrInvalidLimits reports a zero or negative resource budget. ErrInvalidLimits = errors.New("manual clock: invalid limits") )
Functions ¶
This section is empty.
Types ¶
type Callback ¶
type Callback struct {
// contains filtered or unexported fields
}
Callback is a concurrency-safe scheduled function created by Clock.AfterFunc. Its zero value is not usable. Clock advancement owns started invocations; stopping or closing the clock cannot interrupt a function already running.
func (*Callback) Reset ¶
Reset reschedules the callback and reports prior scheduling activity, not whether an invocation is running. Non-positive durations are immediately due. A running invocation is not awaited; explicit reentrant/concurrent progress may start an overlapping invocation. ErrClosed, ErrActiveLimit when reactivating, and clock.ErrOverflow preserve the prior schedule on rejection.
type Clock ¶
type Clock struct {
// contains filtered or unexported fields
}
Clock is a concurrency-safe deterministic clock. Time changes only through Advance, AdvanceTo, or Jump. Construct it with New; the zero value is not a usable clock. Do not copy a Clock after use.
State and resource Stop/Reset methods share one mutex. Reading time, creating resources, advancing, jumping and closing may run concurrently. Construction starts no goroutine; an advancement coordinator starts owned callback goroutines outside the mutex. Callbacks must eventually return; Close cannot terminate them. The caller owns Close and callback cooperation.
func New ¶
New constructs a clock at an explicit wall timestamp, including time.Time{}. It preserves the location and strips any process-local monotonic reading so Jump can model wall movement independently from elapsed progress. Nil options are ignored; an invalid option returns nil and its error. Default limits are 65,536 scheduled objects, 65,536 waiters, and 1,000,000 fired events per coordinator run. The caller must Close the returned clock.
func (*Clock) Advance ¶
Advance requests non-negative elapsed progress from the current instant. The first request runs the coordinator synchronously; nested or concurrent requests return a Waiter without starting another coordinator. Events become due in deadline and registration order, with callbacks outside internal locks.
Running callbacks freeze implicit future progress. Same-instant work may run; a callback waiting for future work must submit a nested Advance and call Wait to allow progress through its target. Arbitrary callbacks that never return can block the coordinating Advance; Advance itself has no cancellation input.
Invalid duration, closure, waiter limits and target overflow return no waiter. Work-limit failure may return a non-nil waiter and ErrWorkLimit; Wait then yields a partial Result. Already-started callbacks are drained on that failure. Use the waiter to synchronize accepted work, including reentrant requests.
func (*Clock) AdvanceTo ¶
AdvanceTo moves forward until target wall time. Backward wall movement must use Jump so it cannot accidentally reverse monotonic progress. Targets farther away than time.Duration can represent return clock.ErrOverflow. Target conversion and request registration are separate operations; a concurrent Advance or Jump can change the wall time between them.
func (*Clock) AfterFunc ¶
AfterFunc schedules an owned callback. A panic is recovered and counted in the advancement Result; panic payloads are never retained. A nil function returns nil and clock.ErrInvalidCallback. Non-positive durations become due at the current instant, but no callback starts until advancement. Scheduling can return ErrClosed, ErrActiveLimit or clock.ErrOverflow. Functions may reenter the clock, but must cooperate with advancement and eventually return.
func (*Clock) Close ¶ added in v1.1.0
Close immediately and idempotently releases every active object owned by the clock. It wakes active sleepers and fails pending advancement waiters with ErrClosed, stops future scheduled events and starts no goroutine. It always returns nil, including repeated calls. Existing timer/ticker channels remain open and any buffered value remains readable. Read-only time methods remain available. Running callbacks are neither stopped nor awaited; an already-running Advance can still be blocked by them after Close returns.
func (*Clock) Jump ¶
Jump changes wall time without changing monotonic progress or event deadlines. Negative deltas are valid. ErrClosed and clock.ErrOverflow leave the wall offset unchanged; overflow is checked against the accumulated jump duration.
func (*Clock) Measure ¶
Measure captures current monotonic progress and returns a concurrency-safe closure whose result is unaffected by Jump.
func (*Clock) NewTicker ¶
NewTicker creates an owned ticker. Its one-element channel drops ticks while the receiver is backpressured, matching the standard library policy. A non-positive period returns nil and clock.ErrInvalidDuration. Scheduling can also return ErrClosed, ErrActiveLimit or clock.ErrOverflow. The owner must Stop the ticker; failure to compute its next deadline automatically stops it.
func (*Clock) NewTimer ¶
NewTimer creates an owned one-shot timer with a one-value buffered channel. Non-positive durations are due at the current instant but require Advance to fire. Failure returns nil with ErrClosed, ErrActiveLimit or clock.ErrOverflow; stopping an unused timer releases its schedule.
func (*Clock) Since ¶
Since returns wall-clock subtraction against Now. Use Mark and SinceMark for elapsed measurement that must remain correct across Jump. The result may be negative after a backward jump or when start is in the future.
func (*Clock) SinceMark ¶
SinceMark returns monotonic progress since mark, independent of wall jumps. Use a Mark from this clock; arbitrary tokens are not validated.
func (*Clock) Sleep ¶
Sleep blocks until manual advancement reaches the deadline or ctx is done. A nil context panics on an open clock. Closed clocks return ErrClosed before checking context or duration. Otherwise a canceled context wins before registration, and non-positive durations succeed without scheduling work. Scheduling can fail with ErrClosed, ErrActiveLimit or clock.ErrOverflow. Close wakes registered sleepers with ErrClosed; cancellation releases their schedule. If completion, closure and cancellation race, either outcome may win.
type Fixed ¶
type Fixed struct {
// contains filtered or unexported fields
}
Fixed is an immutable, concurrency-safe wall clock. Its zero value returns time.Time{}; it has no scheduled resources or release obligation.
func NewFixed ¶
NewFixed returns an immutable clock fixed at now, preserving its location and any process-local monotonic reading. It accepts time.Time{}.
type Limits ¶
type Limits struct {
// MaxActive independently caps scheduled objects and outstanding waiters.
// Running callbacks have already left the scheduled-object count.
MaxActive int
// MaxWorkPerAdvance caps fired events in one coordinator run, including
// concurrent/nested requests and ticker ticks dropped by backpressure.
MaxWorkPerAdvance int
}
Limits bounds scheduled objects, outstanding advancement waiters, and work processed by a Clock. MaxActive applies independently to scheduled objects and advancement waiters.
type Option ¶
type Option func(*config) error
Option configures a Clock during construction.
func WithLimits ¶
WithLimits replaces the default active-object and advancement budgets. Both fields must be positive or New returns nil and ErrInvalidLimits.
type Result ¶
type Result struct {
// StartedAt is elapsed progress when the request was registered.
StartedAt time.Duration
// EndedAt is the requested target on success or progress at failure.
EndedAt time.Duration
// Triggered counts fired events, including undelivered ticker ticks.
Triggered int
// Callbacks counts callback invocations started after submission.
Callbacks int
// Panics counts recovered callback panics recorded after submission.
Panics int
}
Result summarizes work relative to an advancement request's submission. Concurrent/nested requests share a coordinator, so their counts can overlap. A failed request reports partial work; its counts are captured when it fails, not updated for callbacks that finish later during draining.
type Snapshot ¶
type Snapshot struct {
// Now is the wall timestamp, including the accumulated jump offset.
Now time.Time
// Elapsed is manually advanced progress, unaffected by wall jumps.
Elapsed time.Duration
// Active counts scheduled objects, excluding running callbacks and waiters.
Active int
// Closed reports whether Close has released scheduled work.
Closed bool
}
Snapshot is a bounded view of manual-clock state.
type Ticker ¶
type Ticker struct {
// contains filtered or unexported fields
}
Ticker is a concurrency-safe manually advanced periodic timer created by Clock.NewTicker. Its zero value is not usable; the owner must Stop it.
func (*Ticker) C ¶
C returns the ticker's one-value buffered channel; undrained later ticks are dropped. Stop and Clock.Close never close or drain it.
func (*Ticker) Reset ¶
Reset changes the period and schedules the next tick from current elapsed progress without draining an old buffered tick. Non-positive periods return clock.ErrInvalidDuration. ErrClosed, ErrActiveLimit when reactivating, and clock.ErrOverflow also reject the reset without changing the prior schedule.
type Timer ¶
type Timer struct {
// contains filtered or unexported fields
}
Timer is a concurrency-safe manually advanced one-shot timer created by Clock.NewTimer. Its zero value is not usable; the clock owns its schedule.
func (*Timer) C ¶
C returns the timer's one-value buffered channel. It is never closed by Stop or Clock.Close. A delivered timestamp includes the current wall offset.
func (*Timer) Reset ¶
Reset reschedules the timer and reports whether it was active beforehand. Non-positive durations become due at the current instant. A successful reset drains any old buffered timestamp; rejected resets preserve schedule/value. Errors are ErrClosed, ErrActiveLimit when reactivating, or clock.ErrOverflow.
type Waiter ¶
type Waiter struct {
// contains filtered or unexported fields
}
Waiter synchronizes completion of work attributed to an advancement request. Obtain it from Advance or AdvanceTo; its zero value is not usable. Wait may be called concurrently or repeatedly. Context cancellation cancels only that Wait call, not the underlying request or callbacks.
func (*Waiter) Wait ¶
Wait returns the completed result, including partial work with ErrWorkLimit or ErrClosed, or a zero Result with ctx.Err() if the pending wait is canceled. An already-completed waiter returns its result even with a canceled context. For a pending waiter, ctx must be non-nil. Waiting explicitly permits future progress through this request's target while callbacks are running.