import SetInterval
import SetIntervalT
import Control.Concurrent
import Control.Exception
import Control.Monad.State
sprint :: (Show b) => MVar () -> b -> IO ()
sprint mvar b = do
putMVar mvar ()
print b
takeMVar mvar
main :: IO ()
main = do
logMVar <- newEmptyMVar
mvar <- newEmptyMVar
forkIO $ setInterval 1000 (1, 1) $
\ (x, y) -> do
sprint logMVar $ "fib1 " ++ show x
when (x > 100) $ putMVar mvar () -- exit the app at some point!
return (y, x + y)
forkIO $ setIntervalT 1000 (1, 1)
(do
(x, y) <- get
lift $ sprint logMVar $ "fib2 " ++ show x
put (y, x + y)
)
takeMVar mvar
module SetIntervalT (setIntervalT)
where
import Control.Monad.State
import Control.Concurrent
import Control.Exception
setIntervalT :: Int -> a -> StateT a IO () -> IO ()
setIntervalT microsecs a action = do
mvar <- newEmptyMVar
_ <- evalStateT (setInterval' microsecs mvar action) a
takeMVar mvar
setInterval' :: Int -> MVar () -> StateT a IO () -> StateT a IO ThreadId
setInterval' microsecs mvar action = do
i <- get
lift $ forkIO (evalStateT loop i `finally` putMVar mvar ())
where
loop = do
lift $ threadDelay microsecs
action
loop
module SetInterval (setInterval)
where
import Control.Concurrent
import Control.Exception
import Control.Monad
setInterval :: Int -> a -> (a -> IO a) -> IO ()
setInterval microsecs a action = do
mvar <- newEmptyMVar
_ <- setInterval' microsecs a mvar action
takeMVar mvar
setInterval' :: Int -> a -> MVar () -> (a -> IO a) -> IO ThreadId
setInterval' microsecs a mvar action =
forkIO $ loop a `finally` putMVar mvar ()
where
loop i = do
threadDelay microsecs
j <- action i
loop j