| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
TimerWheel
Description
This module is intended to be imported qualified:
import TimerWheel (TimerWheel) import TimerWheel qualified
Synopsis
- data TimerWheel
- data Config = Config {
- spokes :: !Int
- resolution :: !Seconds
- type Seconds = Fixed E9
- data Timer a
- create :: Scope -> Config -> IO TimerWheel
- with :: Config -> (TimerWheel -> IO a) -> IO a
- count :: TimerWheel -> IO Int
- register :: TimerWheel -> Seconds -> IO () -> IO (Timer Bool)
- register_ :: TimerWheel -> Seconds -> IO () -> IO ()
- recurring :: TimerWheel -> Seconds -> IO () -> IO (Timer ())
- recurring_ :: TimerWheel -> Seconds -> IO () -> IO ()
- cancel :: Timer a -> IO a
Timer wheel
data TimerWheel Source #
A timer wheel is a vector-of-collections-of timers to fire. Timers may be one-shot or recurring, and may be scheduled arbitrarily far in the future.
A timer wheel is configured with a spoke count and resolution:
The spoke count determines the size of the timer vector.
A larger spoke count will require more memory, but will result in less insert contention.
The resolution determines the duration of time that each spoke corresponds to, and thus how often timers are checked for expiry.
For example, in a timer wheel with a resolution of
1 second, a timer that is scheduled to fire at8.4 o'clockwill end up firing around9.0 o'clockinstead (that is, on the1 second-boundary).A larger resolution will result in more insert contention and less accurate timers, but will require fewer wakeups by the timeout thread.
The timeout thread has some important properties:
- There is only one, and it fires expired timers synchronously. If your timer actions execute quicky, you can
registerthem directly. Otherwise, consider registering an action that enqueues the real action to be performed on a job queue. - A synchronous exception thrown by a registered timer will bring the timeout thread down, and the exception will be propagated to the thread that created the timer wheel. If you want to log and ignore exceptions, for example, you will have to bake this into the registered actions yourself.
API summary
| Create | Query | Modify |
|---|---|---|
create | count | register |
with | register_ | |
recurring | ||
recurring_ |
Timer wheel configuration
A timer wheel config.
spokesmust be ∈[1, maxBound], and is set to1024if invalid.resolutionmust be ∈(0, ∞], and is set to1if invalid.
API summary
| Create |
|---|
Config |
Constructors
| Config | |
Fields
| |
Instances
| Generic Config Source # | |||||
Defined in TimerWheel Associated Types
| |||||
| Show Config Source # | |||||
| type Rep Config Source # | |||||
Defined in TimerWheel type Rep Config = D1 ('MetaData "Config" "TimerWheel" "timer-wheel-1.0.0.1-inplace" 'False) (C1 ('MetaCons "Config" 'PrefixI 'True) (S1 ('MetaSel ('Just "spokes") 'SourceUnpack 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: S1 ('MetaSel ('Just "resolution") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Seconds))) | |||||
type Seconds = Fixed E9 Source #
A number of seconds, with nanosecond precision.
You can use numeric literals to construct a value of this type, e.g. 0.5.
Otherwise, to convert from a type like Int or Double, you can use the generic numeric conversion function
realToFrac.
Timer
A registered timer, parameterized by the result of attempting to cancel it:
- A one-shot timer may only be canceled if it has not already fired.
- A recurring timer can always be canceled.
API summary
| Create | Modify |
|---|---|
register | cancel |
recurring |
Constructing a timer wheel
Arguments
| :: Config | |
| -> (TimerWheel -> IO a) | |
| -> IO a | |
Perform an action with a timer wheel.
Querying a timer wheel
count :: TimerWheel -> IO Int Source #
Get the number of timers in a timer wheel.
O(1).
Registering timers in a timer wheel
Arguments
| :: TimerWheel | The timer wheel |
| -> Seconds | The delay before the action is fired |
| -> IO () | The action to fire |
| -> IO (Timer Bool) | The timer |
register wheel delay action registers action in wheel to fire after delay seconds.
When canceled, the timer returns whether or not the cancelation was successful; False means the timer had either
already fired, or had already been canceled.
Arguments
| :: TimerWheel | The timer wheel |
| -> Seconds | The delay before the action is fired |
| -> IO () | The action to fire |
| -> IO () |
Like register, but for when you don't intend to cancel the timer.
Arguments
| :: TimerWheel | The timer wheel |
| -> Seconds | The delay before each action is fired |
| -> IO () | The action to fire repeatedly |
| -> IO (Timer ()) | The timer |
recurring wheel action delay registers action in wheel to fire in delay seconds, and every
delay seconds thereafter.
Arguments
| :: TimerWheel | |
| -> Seconds | The delay before each action is fired |
| -> IO () | The action to fire repeatedly |
| -> IO () |
Like recurring, but for when you don't intend to cancel the timer.