module Data.Machine.Regulated where
import Control.Concurrent (threadDelay)
import Control.Monad (when)
import Control.Monad.IO.Class (MonadIO(..))
import Data.Machine.Plan
import Data.Machine.Process
import Data.Machine.Type
import Data.Time.Clock (getCurrentTime, diffUTCTime)
regulated :: MonadIO m => Double -> ProcessT m a a
regulated target = construct $ liftIO getCurrentTime >>= go 0
where go dt prevT =
do await >>= yield
t <- liftIO getCurrentTime
let e = target realToFrac (diffUTCTime t prevT)
dt' = dt + 0.5 * e
when (dt' > 0) (liftIO . threadDelay . round $ dt' * 1000000)
go dt' t