on bcd787e help sign in
74 lines 2.5 kB history raw
1-- |
2-- Module : Streamly.Time
3-- Copyright : (c) 2017 Harendra Kumar
4--
5-- License : BSD3
6-- Maintainer : harendra.kumar@gmail.com
7-- Stability : experimental
8-- Portability : GHC
9--
10-- Time utilities for reactive programming.
12module Streamly.Time
13{-# DEPRECATED
14 "Please use the \"rate\" combinator instead of the functions in this module"
15 #-}
16 ( periodic
17 , withClock
18 )
19where
21import Control.Monad (when)
22import Control.Concurrent (threadDelay)
24-- | Run an action forever periodically at the given frequency specified in per
25-- second (Hz).
26--
27-- @since 0.1.0
28{-# DEPRECATED periodic "Please use the \"rate\" combinator instead" #-}
29periodic :: Int -> IO () -> IO ()
30periodic freq action = do
31 action
32 threadDelay (1000000 `div` freq)
33 periodic freq action
35-- | Run a computation on every clock tick, the clock runs at the specified
36-- frequency. It allows running a computation at high frequency efficiently by
37-- maintaining a local clock and adjusting it with the provided base clock at
38-- longer intervals. The first argument is a base clock returning some notion
39-- of time in microseconds. The second argument is the frequency in per second
40-- (Hz). The third argument is the action to run, the action is provided the
41-- local time as an argument.
42--
43-- @since 0.1.0
44{-# DEPRECATED withClock "Please use the \"rate\" combinator instead" #-}
45withClock :: IO Int -> Int -> (Int -> IO ()) -> IO ()
46withClock clock freq action = do
47 t <- clock
48 go t period period t 0
50 where
52 period = 1000000 `div` freq
54 -- Note that localTime is roughly but not exactly equal to (lastAdj + tick
55 -- * n). That is because we do not abruptly adjust the clock skew instead
56 -- we adjust the tick size.
57 go lastAdj delay tick localTime n = do
58 action localTime
59 when (delay > 0) $ threadDelay delay
61 if n == freq
62 then do
63 (t, newTick, newDelay) <- adjustClock lastAdj localTime delay
64 go t newDelay newTick (localTime + newTick) 0
65 else go lastAdj delay tick (localTime + tick) (n + 1)
67 -- Adjust the tick size rather than the clock to avoid abrupt changes
68 -- resulting in jittery behavior at the end of every interval.
69 adjustClock lastAdj localTime delay = do
70 baseTime <- clock
71 let newTick = period + (baseTime - localTime) `div` freq
72 lastPeriod = (baseTime - lastAdj) `div` freq
73 newDelay = max 0 (delay + period - lastPeriod)
74 return (baseTime, newTick, newDelay)