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

-- | Efficiently run periodic, on-demand actions
--   
--   API docs and the README are available at
--   http://www.stackage.org/package/auto-update.
@package auto-update
@version 0.2.6

module Control.AutoUpdate.Internal
data UpdateState a
UpdateState :: (a -> IO a) -> IORef a -> Int -> TVar Bool -> IORef (IO ()) -> UpdateState a
[usUpdateAction_] :: UpdateState a -> a -> IO a
[usLastResult_] :: UpdateState a -> IORef a
[usIntervalMicro_] :: UpdateState a -> Int
[usTimeHasCome_] :: UpdateState a -> TVar Bool
[usDeleteTimeout_] :: UpdateState a -> IORef (IO ())

-- | 
--   >>> iref <- newIORef (0 :: Int)
--   
--   >>> action = modifyIORef iref (+ 1) >> readIORef iref
--   
--   >>> (getValue, closeState) <- mkClosableAutoUpdate $ defaultUpdateSettings { updateFreq = 200_000, updateAction = action }
--   
--   >>> getValue
--   1
--   
--   >>> threadDelay 100_000 >> getValue
--   1
--   
--   >>> threadDelay 200_000 >> getValue
--   2
--   
--   >>> closeState
--   
mkClosableAutoUpdate :: UpdateSettings a -> IO (IO a, IO ())

-- | provide UpdateState for debugging
mkClosableAutoUpdate' :: UpdateSettings a -> IO (IO a, IO (), UpdateState a)

-- | In a multithreaded environment, sharing results of actions can
--   dramatically improve performance. For example, web servers need to
--   return the current time with each HTTP response. For a high-volume
--   server, it's much faster for a dedicated thread to run every second,
--   and write the current time to a shared IORef, than it is for
--   each request to make its own call to getCurrentTime.
--   
--   But for a low-volume server, whose request frequency is less than once
--   per second, that approach will result in more calls to
--   getCurrentTime than necessary, and worse, kills idle GC.
--   
--   This library solves that problem by allowing you to define actions
--   which will either be performed by a dedicated thread, or, in times of
--   low volume, will be executed by the calling thread.
--   
--   Example usage:
--   
--   
--   import Data.Time
--   import Control.AutoUpdate
--   
--   getTime <- mkAutoUpdate defaultUpdateSettings
--                { updateAction = getCurrentTime
--                , updateFreq = 1000000 -- The default frequency, once per second
--                }
--   currentTime <- getTime
--   
--   
--   For more examples, see the blog post introducing this library.
module Control.AutoUpdate

-- | Settings to control how values are updated.
--   
--   This should be constructed using defaultUpdateSettings and
--   record update syntax, e.g.:
--   
--   
--   let settings = defaultUpdateSettings { updateAction = getCurrentTime }
--   
data UpdateSettings a

-- | Default value for creating an UpdateSettings.
defaultUpdateSettings :: UpdateSettings ()

-- | Action to be performed to get the current value.
--   
--   Default: does nothing.
updateAction :: UpdateSettings a -> IO a

-- | Microseconds between update calls. Same considerations as
--   threadDelay apply.
--   
--   Default: 1000000 microseconds (1 second)
updateFreq :: UpdateSettings a -> Int

-- | Obsoleted field.
updateSpawnThreshold :: UpdateSettings a -> Int

-- | Label of the thread being forked.
--   
--   Default: AutoUpdate
updateThreadName :: UpdateSettings a -> String
mkAutoUpdate :: UpdateSettings a -> IO (IO a)
mkAutoUpdateWithModify :: UpdateSettings a -> (a -> IO a) -> IO (IO a)

-- | Unstable API which exposes internals for testing.
module Control.Debounce.Internal

-- | Settings to control how debouncing should work.
--   
--   This should be constructed using defaultDebounceSettings and
--   record update syntax, e.g.:
--   
--   
--   let settings = defaultDebounceSettings { debounceAction = flushLog }
--   
data DebounceSettings
DebounceSettings :: Int -> IO () -> DebounceEdge -> String -> DebounceSettings

-- | Length of the debounce timeout period in microseconds.
--   
--   Default: 1 second (1000000)
[debounceFreq] :: DebounceSettings -> Int

-- | Action to be performed.
--   
--   Note: all exceptions thrown by this action will be silently discarded.
--   
--   Default: does nothing.
[debounceAction] :: DebounceSettings -> IO ()

-- | Whether to perform the action on the leading edge or trailing edge of
--   the timeout.
--   
--   Default: leadingEdge.
[debounceEdge] :: DebounceSettings -> DebounceEdge

-- | Label of the thread spawned when debouncing.
--   
--   Default: Debounce.
[debounceThreadName] :: DebounceSettings -> String

-- | Setting to control whether the action happens at the leading and/or
--   trailing edge of the timeout.
data DebounceEdge

-- | Perform the action immediately, and then begin a cooldown period. If
--   the trigger happens again during the cooldown, wait until the end of
--   the cooldown and then perform the action again, then enter a new
--   cooldown period.
Leading :: DebounceEdge

-- | Perform the action immediately, and then begin a cooldown period. If
--   the trigger happens again during the cooldown, it is ignored.
LeadingMute :: DebounceEdge

-- | Start a cooldown period and perform the action when the period ends.
--   If another trigger happens during the cooldown, it has no effect.
Trailing :: DebounceEdge

-- | Start a cooldown period and perform the action when the period ends.
--   If another trigger happens during the cooldown, it restarts the
--   cooldown again.
TrailingDelay :: DebounceEdge

-- | Perform the action immediately, and then begin a cooldown period. If
--   the trigger happens again during the cooldown, wait until the end of
--   the cooldown and then perform the action again, then enter a new
--   cooldown period.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !   !         !            !
--    ....... ....... .......    .......
--   X       X       X          X
--   
leadingEdge :: DebounceEdge

-- | Perform the action immediately, and then begin a cooldown period. If
--   the trigger happens again during the cooldown, it is ignored.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !   !      !     !
--    .......    .......
--   X          X
--   
leadingMuteEdge :: DebounceEdge

-- | Start a cooldown period and perform the action when the period ends.
--   If another trigger happens during the cooldown, it has no effect.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !     !     !  !
--    .......     .......
--           X           X
--   
trailingEdge :: DebounceEdge

-- | Start a cooldown period and perform the action when the period ends.
--   If another trigger happens during the cooldown, it restarts the
--   cooldown again.
--   
--   N.B. If a trigger happens DURING the debounceAction it
--   starts a new cooldown. So if the debounceAction takes
--   longer than the debounceFreq, it might run again before
--   the previous action has ended.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !           !  !    !
--    .......     ...............
--           X                   X
--   
trailingDelayEdge :: DebounceEdge
mkDebounceInternal :: MVar () -> (Int -> IO ()) -> DebounceSettings -> IO (IO ())
instance GHC.Classes.Eq Control.Debounce.Internal.DebounceEdge
instance GHC.Internal.Show.Show Control.Debounce.Internal.DebounceEdge

-- | Debounce an action, ensuring it doesn't occur more than once for a
--   given period of time.
--   
--   This is useful as an optimization, for example to ensure that logs are
--   only flushed to disk at most once per second.
--   
--   Example usage:
--   
--   
--   > printString <- mkDebounce defaultDebounceSettings
--                    { debounceAction = putStrLn "Running action"
--                    , debounceFreq = 5000000 -- 5 seconds
--                    , debounceEdge = trailingEdge -- Trigger on the trailing edge
--                    }
--   > printString
--   Running action
--   > printString
--   <Wait five seconds>
--   Running action
--   
--   
--   See the fast-logger package (System.Log.FastLogger) for
--   real-world usage.
module Control.Debounce

-- | Generate an action which will trigger the debounced action to be
--   performed.
--   
--   N.B. The generated action will always immediately return,
--   regardless of the debounceFreq, as the debounced
--   action (and the delay/cooldown) is always performed in a separate
--   thread.
mkDebounce :: DebounceSettings -> IO (IO ())

-- | Settings to control how debouncing should work.
--   
--   This should be constructed using defaultDebounceSettings and
--   record update syntax, e.g.:
--   
--   
--   let settings = defaultDebounceSettings { debounceAction = flushLog }
--   
data DebounceSettings

-- | Default value for creating a DebounceSettings.
defaultDebounceSettings :: DebounceSettings

-- | Length of the debounce timeout period in microseconds.
--   
--   Default: 1 second (1000000)
debounceFreq :: DebounceSettings -> Int

-- | Action to be performed.
--   
--   Note: all exceptions thrown by this action will be silently discarded.
--   
--   Default: does nothing.
debounceAction :: DebounceSettings -> IO ()

-- | Whether to perform the action on the leading edge or trailing edge of
--   the timeout.
--   
--   Default: leadingEdge.
debounceEdge :: DebounceSettings -> DebounceEdge

-- | Label of the thread spawned when debouncing.
--   
--   Default: Debounce.
debounceThreadName :: DebounceSettings -> String

-- | Perform the action immediately, and then begin a cooldown period. If
--   the trigger happens again during the cooldown, wait until the end of
--   the cooldown and then perform the action again, then enter a new
--   cooldown period.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !   !         !            !
--    ....... ....... .......    .......
--   X       X       X          X
--   
leadingEdge :: DebounceEdge

-- | Perform the action immediately, and then begin a cooldown period. If
--   the trigger happens again during the cooldown, it is ignored.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !   !      !     !
--    .......    .......
--   X          X
--   
leadingMuteEdge :: DebounceEdge

-- | Start a cooldown period and perform the action when the period ends.
--   If another trigger happens during the cooldown, it has no effect.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !     !     !  !
--    .......     .......
--           X           X
--   
trailingEdge :: DebounceEdge

-- | Start a cooldown period and perform the action when the period ends.
--   If another trigger happens during the cooldown, it restarts the
--   cooldown again.
--   
--   N.B. If a trigger happens DURING the debounceAction it
--   starts a new cooldown. So if the debounceAction takes
--   longer than the debounceFreq, it might run again before
--   the previous action has ended.
--   
--   Example of how this style debounce works:
--   
--   
--   ! = function execution
--   . = cooldown period
--   X = debounced code execution
--   
--   !           !  !    !
--    .......     ...............
--           X                   X
--   
trailingDelayEdge :: DebounceEdge

module Control.Reaper.Internal

-- | A data structure to hold reaper APIs.
data Reaper workload item
Reaper :: (item -> IO ()) -> IO workload -> ((workload -> workload) -> IO workload) -> IO workload -> IO () -> Reaper workload item

-- | Adding an item to the workload
[reaperAdd] :: Reaper workload item -> item -> IO ()

-- | Reading workload.
[reaperRead] :: Reaper workload item -> IO workload

-- | Modify the workload. The resulting workload is returned.
--   
--   If there is no reaper thread, the modifier will not be applied and
--   reaperEmpty will be returned.
--   
--   If the reaper is currently executing jobs, those jobs will not be in
--   the given workload and the workload might appear empty.
--   
--   If all jobs are removed by the modifier, the reaper thread will not be
--   killed. The reaper thread will only terminate if reaperKill is
--   called or the result of reaperAction satisfies
--   reaperNull.
[reaperModify] :: Reaper workload item -> (workload -> workload) -> IO workload

-- | Stopping the reaper thread if exists. The current workload is
--   returned.
[reaperStop] :: Reaper workload item -> IO workload

-- | Killing the reaper thread immediately if exists.
[reaperKill] :: Reaper workload item -> IO ()

-- | This module provides the ability to create reapers: dedicated cleanup
--   threads. These threads will automatically spawn and die based on the
--   presence of a workload to process on. Example uses include:
--   
--   
--   
- Killing long-running jobs
--   
- Closing unused connections in a connection pool
--   
- Pruning a cache of old items (see example below)
--   
--   
--   For real-world usage, search the WAI family of packages for
--   imports of Control.Reaper.
module Control.Reaper

-- | Settings for creating a reaper. This type has two parameters:
--   workload gives the entire workload, whereas item
--   gives an individual piece of the queue. A common approach is to have
--   workload be a list of items. This is encouraged by
--   defaultReaperSettings and mkListAction.
data ReaperSettings workload item

-- | Default ReaperSettings value, biased towards having a list of
--   work items.
defaultReaperSettings :: ReaperSettings [item] item

-- | The action to perform on a workload. The result of this is a "workload
--   modifying" function. In the common case of using lists, the result
--   should be a difference list that prepends the remaining workload to
--   the temporary workload. The temporary workload here refers to items
--   added to the workload while the reaper action is running. For help
--   with setting up such an action, see mkListAction.
--   
--   Default: do nothing with the workload, and then prepend it to the
--   temporary workload. This is incredibly useless; you should definitely
--   override this default.
reaperAction :: ReaperSettings workload item -> workload -> IO (workload -> workload)

-- | Number of microseconds to delay between calls of reaperAction.
--   
--   Default: 30 seconds.
reaperDelay :: ReaperSettings workload item -> Int

-- | Add an item onto a workload.
--   
--   Default: list consing.
reaperCons :: ReaperSettings workload item -> item -> workload -> workload

-- | Check if a workload is empty, in which case the worker thread will
--   shut down.
--   
--   Default: null.
reaperNull :: ReaperSettings workload item -> workload -> Bool

-- | An empty workload.
--   
--   Default: empty list.
reaperEmpty :: ReaperSettings workload item -> workload

-- | Label of the thread spawned by the reaper.
--   
--   Default: Reaper.
reaperThreadName :: ReaperSettings workload item -> String

-- | A data structure to hold reaper APIs.
data Reaper workload item

-- | Adding an item to the workload
reaperAdd :: Reaper workload item -> item -> IO ()

-- | Reading workload.
reaperRead :: Reaper workload item -> IO workload

-- | Modify the workload. The resulting workload is returned.
--   
--   If there is no reaper thread, the modifier will not be applied and
--   reaperEmpty will be returned.
--   
--   If the reaper is currently executing jobs, those jobs will not be in
--   the given workload and the workload might appear empty.
--   
--   If all jobs are removed by the modifier, the reaper thread will not be
--   killed. The reaper thread will only terminate if reaperKill is
--   called or the result of reaperAction satisfies
--   reaperNull.
reaperModify :: Reaper workload item -> (workload -> workload) -> IO workload

-- | Stopping the reaper thread if exists. The current workload is
--   returned.
reaperStop :: Reaper workload item -> IO workload

-- | Killing the reaper thread immediately if exists.
reaperKill :: Reaper workload item -> IO ()

-- | Create a reaper addition function. This function can be used to add
--   new items to the workload. Spawning of reaper threads will be handled
--   for you automatically.
mkReaper :: ReaperSettings workload item -> IO (Reaper workload item)

-- | A helper function for creating reaperAction functions. You
--   would provide this function with a function to process a single work
--   item and return either a new work item, or Nothing if the
--   work item is expired.
mkListAction :: (item -> IO (Maybe item')) -> [item] -> IO ([item'] -> [item'])
