Concurrency demos/Two reader threads
Jump to navigation Jump to search
This is an example of using a main thread to send messages to 2 reader threads, over a single chan. It uses lazy IO to convert the Chan into a lazy list of filtered elements, and passes the filtered lists to the reader threads. The advantage of this design is a greatly simplified reader implementation (as it need do no IO).
-- -- ghc chantest.hs -o chantest -- Usage: Enter "1", "2" or "0" to exit. -- import System.IO import Control.Concurrent import Control.Concurrent.Chan import Text.Printf -- -- Rather tha wait on multiple channels, it strikes me that you could -- have a single channel, and tag each thread's input. then lazily -- stream the chans contents through a filter, passing the *pure* list -- of filtered elements to a consuming thread -- type Pipe = Chan (Either String String) main :: IO () main = do chan <- newChan :: IO Pipe s <- getChanContents chan -- lazy list of chan elements c1Thread <- forkIO $ reader "c1" (catLeft s) -- read only Lefts c2Thread <- forkIO $ reader "c2" (catRight s) -- read only Rights writer chan where catLeft ls = [x | Left x <- ls] catRight ls = [x | Right x <- ls] writer :: Pipe -> IO () writer chan = loop where loop = getChar >>= command command '0' = print "done" command '1' = writeChan chan (Left "main: 1") >> loop command '2' = writeChan chan (Right "main: 2") >> loop command '\n' = loop -- ignore command c = printf "Illegal: %c\n" c >> loop reader :: String -> [String] -> IO () reader name xs = mapM_ (printf "%s %s\n" name) xs
$ ghc x.hs -threaded
$ ./a.out 1 c1 main: 1 2 c2 main: 2 2 c2 main: 2 1 c1 main: 1 2 c2 main: 2 3 Illegal: 3 1 c1 main: 1 2 c2 main: 2 0 "done"