-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A timer wheel
--
-- This library provides a timer wheel data structure for
--
--
-- - O(1) registering IO actions to fire after a given
-- amount of time
-- - O(1) canceling registered actions
--
--
-- It is similar to TimerManager from GHC.Event, but can
-- scale much better under concurrent access patterns.
--
-- An unreleased version of this library has a backpack-based
-- signature for selecting from a variety of different data structures
-- used internally. However, until backpack has broader support
-- on Hackage, and in Haddocks, etc, I decided to just hard-code
-- something decent (a priority search queue). This makes the
-- O(1) claims above a bit of a lie, as these rely on using a
-- linked list data structure internally.
@package timer-wheel
@version 0.1.0
module Data.TimerWheel
-- | A TimerWheel is a vector-of-collections-of timers to fire. It
-- is configured with a spoke count and resolution. A
-- timeout thread is spawned to step through the timer wheel and fire
-- expired timers at regular intervals.
--
--
-- - The spoke count determines the size of the timer
-- vector.
- A larger spoke count will result in less
-- insert contention at each spoke and will require more
-- memory to store the timer wheel.
- A smaller spoke
-- count will result in more insert contention at each spoke
-- and will require less memory to store the timer
-- wheel.
-- - The resolution determines both the duration of time that
-- each spoke corresponds to, and how often the timeout thread wakes. For
-- example, with a resolution of 1s, a timer that expires
-- at 2.5s will not fire until the timeout thread wakes
-- at 3s.
- A larger resolution will result
-- in more insert contention at each spoke, less accurate
-- timers, and will require fewer wakeups by the timeout
-- thread.
- A smaller resolution will result in less
-- insert contention at each spoke, more accurate timers, and
-- will require more wakeups by the timeout thread.
-- - The timeout thread has three important properties:
- There is
-- only one, and it fires expired timers synchronously. If your timer
-- actions execute quicky, register them directly. Otherwise,
-- consider registering an action that enqueues the real action to
-- be performed on a job queue.
- Synchronous exceptions thrown by
-- enqueued IO actions will bring the thread down, and no more
-- timeouts will ever fire. If you want to catch exceptions and log them,
-- for example, you will have to bake this into the registered actions
-- yourself.
- The life of the timeout thread is scoped to the life
-- of the timer wheel. When the timer wheel is garbage collected, the
-- timeout thread will automatically stop doing work, and die
-- gracefully.
--
--
-- Below is a depiction of a timer wheel with 6 timers inserted
-- across 8 spokes, and a resolution of 0.1s.
--
--
-- 0s .1s .2s .3s .4s .5s .6s .7s .8s
-- +-----+-----+-----+-----+-----+-----+-----+-----+
-- | | A | | B,C | D | | | E,F |
-- +-----+-----+-----+-----+-----+-----+-----+-----+
--
data TimerWheel
-- | new n s creates a TimerWheel with n
-- spokes and a resolution of s seconds.
new :: Int -> Fixed E6 -> IO TimerWheel
-- | register n m w registers an action m in timer
-- wheel w to fire after n seconds.
--
-- Returns an action that, when called, attempts to cancel the timer, and
-- returns whether or not it was successful (False means the
-- timer has already fired).
register :: Fixed E6 -> IO () -> TimerWheel -> IO (IO Bool)
-- | Like register, but for when you don't intend to cancel the
-- timer.
register_ :: Fixed E6 -> IO () -> TimerWheel -> IO ()
-- | recurring n m w registers an action m in
-- timer wheel w to fire every n seconds.
--
-- Returns an action that, when called, cancels the recurring timer.
recurring :: Fixed E6 -> IO () -> TimerWheel -> IO (IO ())