Haskell by Example: Timeouts
original{-# LANGUAGE GADTs #-}
import Control.Concurrent
import Control.Concurrent.STM
main = do
c1 <- atomically $ newTQueue
forkIO $ do
threadDelay (2 * 1000000)
atomically $ writeTQueue c1 "result 1"
t1 <- newTimer (1 * 1000000)
select [ Case c1 $ \res -> putStrLn res
, Case t1 $ \_ -> putStrLn "timeout 1"]
c2 <- atomically $ newTQueue
forkIO $ do
threadDelay (2 * 1000000)
atomically $ writeTQueue c2 "result 2"
t2 <- newTimer (3 * 1000000)
select [ Case c2 $ \res -> putStrLn res
, Case t2 $ \_ -> putStrLn "timeout 2"]
type Timer = TMVar ()
newTimer :: Int -> IO Timer
newTimer delay = do
timer <- atomically newEmptyTMVar
forkIO $ do
threadDelay delay
atomically $ putTMVar timer ()
return timer
class Selectable f where
tryRead :: f a -> STM (Maybe a)
instance Selectable TMVar where
tryRead = tryReadTMVar
instance Selectable TQueue where
tryRead = tryReadTQueue
data Select a where
Default :: IO a -> Select a
Case :: Selectable s => s b -> (b -> IO a) -> Select a
select :: [Select a] -> IO a
select [] = error "select: empty list"
select ((Default x):_) = x
select (x@(Case v f):xs) = do
var <- atomically $ tryRead v
case var of
Just b -> f b
Nothing -> select (xs ++ [x])
$ runhaskell timeouts.hs
timeout 1
result 2
back to index