Week 6 Lecture 1
hs
1import Control.Concurrent (2 Chan,3 ThreadId,4 forkIO,5 newChan,6 readChan,7 threadDelay,8 writeChan,9 )10import Control.Monad (forM, forever, void)1112-- forkIO -- Creates a thread13-- newChan -- Creates a new channel14-- writeChan -- Writes to the channel's message queue15-- readChan -- Reads from the channel. Blocks if the channel is empty1617messageExample :: IO ()18messageExample = do19 c <- newChan20 forkIO $ forever $ do21 x <- readChan c22 putStrLn $ "Received: " ++ x23 writeChan c "42"24 writeChan c "43"25 pure ()2627messageExample2 :: IO ()28messageExample2 = do29 c <- newChan30 let threadLoop c = do31 x <- readChan c32 putStrLn $ "Received: " ++ x33 threadLoop c34 forkIO $ threadLoop c35 writeChan c "42"36 writeChan c "43"37 pure ()3839-- Single reader principle40-- A channel shall only be read by one thread, yet can be written by multiple4142---- IncServer BEGIN4344data Msg = MsgInc Int (Chan Int) | MsgSet Int4546newServer :: IO IncServer47newServer = do48 c <- newChan49 let threadLoop state = do50 msg <- readChan c51 case msg of52 MsgInc n rc -> do53 writeChan rc state54 threadLoop $ state + n55 MsgSet n -> threadLoop n56 forkIO $ threadLoop 057 pure $ IncServer $ c5859data IncServer = IncServer (Chan Msg)6061-- This is an RPC operation62serverInc :: IncServer -> Int -> IO Int63serverInc (IncServer c) n = do64 rc <- newChan65 writeChan c $ MsgInc n rc66 readChan rc6768-- This is an asynchronous operation69serverSet :: IncServer -> Int -> IO ()70serverSet (IncServer c) = writeChan c . MsgSet7172usage :: IO ()73usage = do74 s <- newServer75 forM [1 .. 10] $ \i ->76 forkIO $ void $ serverInc s i77 serverSet s 078 r <- serverInc s 079 putStrLn $ show r8081---- IncServer END8283---- GenServer BEGIN8485-- ørlæng (cursed)8687data Server msg = Server ThreadId (Chan msg)8889spawn :: (Chan msg -> IO ()) -> IO (Server msg)90spawn f = do91 c <- newChan92 fid <- forkIO $ f c93 pure $ Server fid c9495send :: Chan msg -> msg -> IO ()96send = writeChan9798receive :: Chan msg -> IO msg99receive = readChan100101-- asynchronous102sendTo :: Server msg -> msg -> IO ()103sendTo (Server _ c) msg = send c msg104105data ReplyChan a = ReplyChan (Chan a)106107reply :: ReplyChan a -> a -> IO ()108reply (ReplyChan c) = send c109110requestReply :: Server msg -> (ReplyChan a -> msg) -> IO a111requestReply server mkMsg = do112 rc <- newChan113 let msg = mkMsg $ ReplyChan rc114 sendTo server msg115 receive rc116117---- GenServer END118119---- IncServer based on GenServer BEGIN120121data ISGMsg122 = ISGMsgInc Int (ReplyChan Int)123 | ISGMsgSet Int124125data ISGServer = ISGServer (Server ISGMsg)126127newISGServer :: IO ISGServer128newISGServer = do129 let serverLoop state c = do130 msg <- receive c131 case msg of132 (ISGMsgInc a rc) -> do133 reply rc state134 serverLoop (state + a) c135 (ISGMsgSet a) -> serverLoop a c136 ISGServer <$> (spawn $ serverLoop 0)137138serverInc' :: Int -> ISGServer -> IO Int139serverInc' x (ISGServer server) = requestReply server (ISGMsgInc x)140141serverSet' :: Int -> ISGServer -> IO ()142serverSet' n (ISGServer server) = sendTo server $ ISGMsgSet n143144---- IncServer based on GenServer END145146usage' :: IO ()147usage' = do148 s <- newISGServer149 serverSet' 3 s150 serverSet' 4 s151 _ <- serverInc' 4 s152 _ <- serverInc' 4 s153 r <- serverInc' 4 s154 putStrLn $ show r155156type Timeout = Int157158readWithTimeout :: Chan a -> Timeout -> IO (Maybe a)159readWithTimeout chan timeout = do160 -- tc :: Chan (Maybe a)161 tc <- newChan162 forkIO $ threadDelay timeout >> writeChan tc Nothing163 forkIO $ readChan chan >>= writeChan tc . Just164 readChan tc165166usage'' :: IO ()167usage'' = do168 c <- newChan169 forkIO $ do170 threadDelay 10000000000171 writeChan c 123172 x <- readWithTimeout c 1000000173 print x174175-- Our job as computer scientists is to take programs that are """exciting""", and make them somehow less """exciting"""176177-- I'm not judging you on taste (in this course)178179-- Space