aboutsummaryrefslogtreecommitdiff
path: root/src/BatchedRunner.hs
blob: 83a704c5097b3e36d3e3405c676aa6bcf5159c1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
module BatchedRunner (
    Runner,
    makeRunner,
    stopRunner,
    notifyRunner,
    withRunner
) where

import Control.Concurrent (forkIO, threadDelay)
import Control.Concurrent.STM.TMVar
import Control.Exception (bracket)
import Control.Monad.STM
import Control.Monad (unless, void)
import Data.Maybe (fromMaybe)

newtype Runner = Runner (TMVar Bool)

makeRunner :: IO a -> Int {- µs -} -> IO Runner
makeRunner f n = do
    mv <- newEmptyTMVarIO
    _ <- forkIO $ runnerLoop mv
    return $ Runner mv

  where runnerLoop mv = do
            b <- atomically $ takeTMVar mv
            unless b $ do
                threadDelay n
                -- clear the TMVar; we're running f now
                mayB <- atomically $ tryTakeTMVar mv
                _ <- f
                unless (fromMaybe False mayB) $ runnerLoop mv

stopRunner :: Runner -> IO ()
stopRunner (Runner mv) = atomically $ putTMVar mv True

notifyRunner :: Runner -> IO ()
notifyRunner (Runner mv) = void $ atomically $ tryPutTMVar mv False

withRunner :: IO a -> Int -> (Runner -> IO b) -> IO b
withRunner f n = bracket (makeRunner f n) stopRunner