Week 6 Lecture 2
hs
1import Control.Concurrent (2 Chan,3 ThreadId,4 forkIO,5 newChan,6 readChan,7 threadDelay,8 writeChan,9 )10import Control.Exception (SomeException, catch, evaluate)11import Control.Monad (forM, forever, void)12import Distribution.Simple.Build (repl)1314-- import GenServer1516data Server msg = Server ThreadId (Chan msg)1718spawn :: (Chan msg -> IO ()) -> IO (Server msg)19spawn f = do20 c <- newChan21 fid <- forkIO $ f c22 pure $ Server fid c2324send :: Chan msg -> msg -> IO ()25send = writeChan2627receive :: Chan msg -> IO msg28receive = readChan2930-- asynchronous31sendTo :: Server msg -> msg -> IO ()32sendTo (Server _ c) msg = send c msg3334data ReplyChan a = ReplyChan (Chan a)3536reply :: ReplyChan a -> a -> IO ()37reply (ReplyChan c) = send c3839requestReply :: Server msg -> (ReplyChan a -> msg) -> IO a40requestReply server mkMsg = do41 rc <- newChan42 let msg = mkMsg $ ReplyChan rc43 sendTo server msg44 receive rc4546--4748type Seconds = Int4950data Status a51 = Value a52 | Timeout53 | Error String54 deriving (Show)5556data Async a = Async (Server (Msg a))5758data Msg a59 = MsgWait (ReplyChan (Status a))60 | MsgPoll (ReplyChan (Maybe (Status a)))61 | MsgPutVal a62 | MsgTimeout63 | MsgError String6465{-66serverLoopOld :: a -> Chan (Msg a) -> IO ()67serverLoopOld x c = do68 msg <- receive c69 case msg of70 MsgWait rc -> do71 reply rc x72 serverLoopOld x c73 MsgPoll rc -> do74 reply rc $ Just x75 serverLoopOld x c76 MsgPutVal a -> undefined77-}7879-- State machine approach8081serverLoopNoVal :: Chan (Msg a) -> [ReplyChan (Status a)] -> IO ()82serverLoopNoVal c waiters = do83 msg <- receive c84 case msg of85 MsgWait rc -> do86 serverLoopNoVal c (rc : waiters)87 MsgPoll rc -> do88 reply rc Nothing89 serverLoopNoVal c waiters90 MsgPutVal a -> do91 mapM_ (\rc -> reply rc (Value a)) waiters92 serverLoopVal (Value a) c93 MsgTimeout -> do94 mapM_ (\rc -> reply rc Timeout) waiters95 serverLoopNoVal c []96 MsgError e -> do97 mapM_ (\rc -> reply rc $ Error e) waiters98 serverLoopVal (Error e) c99100serverLoopVal :: Status a -> Chan (Msg a) -> IO ()101serverLoopVal a c = do102 msg <- receive c103 case msg of104 MsgWait rc -> do105 reply rc $ a106 serverLoopVal a c107 MsgPoll rc -> do108 reply rc $ Just $ a109 serverLoopVal a c110 MsgPutVal _ ->111 serverLoopVal a c112 MsgTimeout -> do113 serverLoopVal a c114 MsgError _ -> do115 serverLoopVal a c116117{-118-- will block only at wait, thx Haskell119asyncLazy :: (b -> a) -> b -> IO (Async a)120asyncLazy f x = do121 s <- spawn $ do122 let y = f x123 serverLoopOld y124 pure $ Async s125126-- when serverLoop :: a -> Chan (Msg a) -> IO ()127asyncBlockServer :: (b -> a) -> b -> IO (Async a)128asyncBlockServer f x = do129 s <- spawn $ \c -> do130 y <- evaluate $ f x131 serverLoopOld y c132 pure $ Async s133-}134135async :: (b -> a) -> b -> IO (Async a)136async f x = do137 s <- spawn $ \c -> do138 forkIO $ do139 y <- evaluate $ f x140 send c $ MsgPutVal y141 serverLoopNoVal c []142 pure $ Async s143144asyncTimeout :: Seconds -> (b -> a) -> b -> IO (Async a)145asyncTimeout t f x = do146 s <- spawn $ \c -> do147 _ <- forkIO $ do148 let comp :: IO ()149 comp = do150 y <- evaluate $ f x151 send c $ MsgPutVal y152 handler :: SomeException -> IO ()153 handler e = do154 send c $ MsgError (show e)155 catch comp handler156 _ <- forkIO $ do157 threadDelay $ t * 1000000158 send c $ MsgTimeout159 serverLoopNoVal c []160 pure $ Async s161162wait :: Async a -> IO (Status a)163wait (Async s) = requestReply s MsgWait164165waitAny :: [Async a] -> IO (Status a)166waitAny [] = error "empty list"167waitAny [x] = wait x168waitAny (x : xs) = do169 c <- newChan170 forkIO $ do171 x' <- wait x172 send c x'173 forkIO $ do174 y' <- waitAny xs175 send c y'176 receive c177178-- Check for computation finish179-- Should respond as quickly as possible180-- Won't work, cause the serverLoop does the job,181-- so it is blocked and cannot answer in time182pollSimple :: Async a -> IO (Maybe (Status a))183pollSimple (Async s) = requestReply s MsgPoll184185poll :: Async a -> IO (Maybe (Status a))186poll (Async s) = requestReply s MsgPoll187188-- DEMOS189190fib :: Int -> Int191fib x192 | x == 0 = 1193 | x == 1 = 1194 | x < 0 = error ""195 | otherwise = (fib (x - 1)) + (fib (x - 2))196197{-198demo1 :: IO ()199demo1 = do200 a <- asyncLazy fib 30201 res <- wait a -- continuation goes on, as the value is not used202 putStrLn "I got the result"203 putStrLn "Here it is:"204 putStrLn $ show res -- lazyness only force the actual blocking here205206demo2 :: IO ()207demo2 = do208 a <- asyncBlockServer fib 30 -- will be eager evaluation at wait209 _ <- pollSimple a210 res <- wait a -- blocks here, as intended211 putStrLn "I got the result"212 putStrLn "Here it is:"213 putStrLn $ show res214-}215216demo3 :: IO ()217demo3 = do218 a <- asyncTimeout 5 fib 30 -- will be eager evaluation at wait219 b <- poll a220 putStrLn $ "Poll returned: " ++ show b221 res <- wait a -- blocks here, as intended222 putStrLn "I got the result"223 putStrLn "Here it is:"224 putStrLn $ show res225226-- No space227228-- We are runnig aout of teaching229230-- Written form exam231-- Dummy exam on the last week232-- Different size, and Maybe different difficulty (best guess according to him)233234-- Finish of week7 exercise is expected, though marked [optional]235236-- No idea how many questions237-- One TA is on it238-- Grading is not based on answer %239240-- on week 8 and anything before exam: nothing planned241-- last lecture is on week 7242243-- Exercise 7 is last year's exam244