streamly-0.7.0: src/Streamly/Internal/Data/Time.hs
{-# OPTIONS_HADDOCK hide #-}
-- |
-- Module : Streamly.Internal.Data.Time
-- Copyright : (c) 2017 Harendra Kumar
--
-- License : BSD3
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
--
-- Time utilities for reactive programming.
module Streamly.Internal.Data.Time
{-# DEPRECATED
"Please use the \"rate\" combinator instead of the functions in this module"
#-}
( periodic
, withClock
)
where
import Control.Monad (when)
import Control.Concurrent (threadDelay)
-- | Run an action forever periodically at the given frequency specified in per
-- second (Hz).
--
-- @since 0.1.0
{-# DEPRECATED periodic "Please use the \"rate\" combinator instead" #-}
periodic :: Int -> IO () -> IO ()
periodic freq action = do
action
threadDelay (1000000 `div` freq)
periodic freq action
-- | Run a computation on every clock tick, the clock runs at the specified
-- frequency. It allows running a computation at high frequency efficiently by
-- maintaining a local clock and adjusting it with the provided base clock at
-- longer intervals. The first argument is a base clock returning some notion
-- of time in microseconds. The second argument is the frequency in per second
-- (Hz). The third argument is the action to run, the action is provided the
-- local time as an argument.
--
-- @since 0.1.0
{-# DEPRECATED withClock "Please use the \"rate\" combinator instead" #-}
withClock :: IO Int -> Int -> (Int -> IO ()) -> IO ()
withClock clock freq action = do
t <- clock
go t period period t 0
where
period = 1000000 `div` freq
-- Note that localTime is roughly but not exactly equal to (lastAdj + tick
-- * n). That is because we do not abruptly adjust the clock skew instead
-- we adjust the tick size.
go lastAdj delay tick localTime n = do
action localTime
when (delay > 0) $ threadDelay delay
if n == freq
then do
(t, newTick, newDelay) <- adjustClock lastAdj localTime delay
go t newDelay newTick (localTime + newTick) 0
else go lastAdj delay tick (localTime + tick) (n + 1)
-- Adjust the tick size rather than the clock to avoid abrupt changes
-- resulting in jittery behavior at the end of every interval.
adjustClock lastAdj localTime delay = do
baseTime <- clock
let newTick = period + (baseTime - localTime) `div` freq
lastPeriod = (baseTime - lastAdj) `div` freq
newDelay = max 0 (delay + period - lastPeriod)
return (baseTime, newTick, newDelay)