-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A timer wheel
--   
--   This library provides a timer wheel data structure for
--   
--   <ul>
--   <li><i>O(1)</i> registering <tt>IO</tt> actions to fire after a given
--   amount of time</li>
--   <li><i>O(1)</i> canceling registered actions</li>
--   </ul>
--   
--   It is similar to <tt>TimerManager</tt> from <a>GHC.Event</a>, but can
--   scale much better under concurrent access patterns.
--   
--   An unreleased version of this library has a <tt>backpack</tt>-based
--   signature for selecting from a variety of different data structures
--   used internally. However, until <tt>backpack</tt> has broader support
--   on Hackage, and in Haddocks, etc, I decided to just hard-code
--   something decent (a priority search queue). This makes the
--   <tt>O(1)</tt> 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 <a>TimerWheel</a> is a vector-of-collections-of timers to fire. It
--   is configured with a <i>spoke count</i> and <i>resolution</i>. A
--   timeout thread is spawned to step through the timer wheel and fire
--   expired timers at regular intervals.
--   
--   <ul>
--   <li>The <i>spoke count</i> determines the size of the timer
--   vector.<ul><li>A <b>larger spoke count</b> will result in <b>less
--   insert contention</b> at each spoke and will require <b>more
--   memory</b> to store the timer wheel.</li><li>A <b>smaller spoke
--   count</b> will result in <b>more insert contention</b> at each spoke
--   and will require <b>less memory</b> to store the timer
--   wheel.</li></ul></li>
--   <li>The <i>resolution</i> determines both the duration of time that
--   each spoke corresponds to, and how often the timeout thread wakes. For
--   example, with a resolution of <b><tt>1s</tt></b>, a timer that expires
--   at <b><tt>2.5s</tt></b> will not fire until the timeout thread wakes
--   at <b><tt>3s</tt></b>.<ul><li>A <b>larger resolution</b> will result
--   in <b>more insert contention</b> at each spoke, <b>less accurate</b>
--   timers, and will require <b>fewer wakeups</b> by the timeout
--   thread.</li><li>A <b>smaller resolution</b> will result in <b>less
--   insert contention</b> at each spoke, <b>more accurate</b> timers, and
--   will require <b>more wakeups</b> by the timeout thread.</li></ul></li>
--   <li>The timeout thread has three important properties:<ul><li>There is
--   only one, and it fires expired timers synchronously. If your timer
--   actions execute quicky, <a>register</a> them directly. Otherwise,
--   consider registering an action that enqueues the <i>real</i> action to
--   be performed on a job queue.</li><li>Synchronous exceptions thrown by
--   enqueued <tt>IO</tt> 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.</li><li>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.</li></ul></li>
--   </ul>
--   
--   Below is a depiction of a timer wheel with <tt>6</tt> timers inserted
--   across <tt>8</tt> spokes, and a resolution of <tt>0.1s</tt>.
--   
--   <pre>
--   0s   .1s   .2s   .3s   .4s   .5s   .6s   .7s   .8s
--   +-----+-----+-----+-----+-----+-----+-----+-----+
--   |     | A   |     | B,C | D   |     |     | E,F |
--   +-----+-----+-----+-----+-----+-----+-----+-----+
--   </pre>
data TimerWheel

-- | <tt>new n s</tt> creates a <a>TimerWheel</a> with <b><tt>n</tt></b>
--   spokes and a resolution of <b><tt>s</tt></b> seconds.
new :: Int -> Fixed E6 -> IO TimerWheel

-- | <tt>register n m w</tt> registers an action <b><tt>m</tt></b> in timer
--   wheel <b><tt>w</tt></b> to fire after <b><tt>n</tt></b> seconds.
--   
--   Returns an action that, when called, attempts to cancel the timer, and
--   returns whether or not it was successful (<tt>False</tt> means the
--   timer has already fired).
register :: Fixed E6 -> IO () -> TimerWheel -> IO (IO Bool)

-- | Like <a>register</a>, but for when you don't intend to cancel the
--   timer.
register_ :: Fixed E6 -> IO () -> TimerWheel -> IO ()

-- | <tt>recurring n m w</tt> registers an action <b><tt>m</tt></b> in
--   timer wheel <b><tt>w</tt></b> to fire every <b><tt>n</tt></b> seconds.
--   
--   Returns an action that, when called, cancels the recurring timer.
recurring :: Fixed E6 -> IO () -> TimerWheel -> IO (IO ())
