Skip to content

Instantly share code, notes, and snippets.

@portnov
Created February 19, 2016 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save portnov/aa634c8c82971239d78a to your computer and use it in GitHub Desktop.
Save portnov/aa634c8c82971239d78a to your computer and use it in GitHub Desktop.
Two-way Chan
module Chan2 where
import Control.Concurrent
type Chan2 rq rs = Chan (rq, MVar rs)
call :: Chan2 rq rs -> rq -> IO rs
call chan rq = do
mvar <- newEmptyMVar
writeChan chan (rq, mvar)
rs <- takeMVar mvar
return rs
processCall :: Chan2 rq rs -> (rq -> IO (rs, x)) -> IO x
processCall chan handler = do
(rq, mvar) <- readChan chan
(rs, x) <- handler rq
putMVar mvar rs
return x
newChan2 :: IO (Chan2 rq rs)
newChan2 = newChan
import Control.Concurrent
import System.IO
import Chan2
type Rq = String
type Rs = String
server :: Chan2 Rq Rs -> IO ()
server chan = do
done <- processCall chan $ \rq ->
if rq == "quit"
then return ("ok", True)
else return (rq ++ rq, False)
if done
then putStrLn "Server quit"
else server chan
client :: Chan2 Rq Rs -> IO ()
client chan = do
putStr "client> "
rq <- getLine
rs <- call chan rq
putStrLn $ "server: " ++ rs
if rq == "quit"
then putStrLn "Client quit"
else client chan
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
chan <- newChan2
forkIO $ server chan
client chan
return ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment