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