Hello, I was trying to write an abstraction for bidirectional communication between two threads. For some reason, MVars seem to break: ----------------------------------------------- class Cords c t u where newCord :: IO (c t u) listen :: c t u -> IO t speak :: c t u -> u -> IO () data Cord t u = Cord (IO (MVar t)) (IO (MVar u)) instance Cords Cord t u where newCord = return (Cord newEmptyMVar newEmptyMVar) speak (Cord _ s) t = do s' <- s ; putMVar s' t listen (Cord h s) = do h' <- h ; takeMVar h' otherEnd (Cord t u) = Cord u t showT :: Cord Int String -> IO () showT cord = do putStrLn "Runnning..." x <- listen cord putStrLn ("Heard " ++ show x) speak cord (show x) putStr ("Said " ++ (show x)) showT cord main :: IO () main = do cord <- newCord forkIO (showT (otherEnd cord)) speak cord 1 str <- listen cord putStrLn str ----------------------------------------------- Hugs writes: Main> main Runnning... Program error: no more threads (deadlock?) (131 reductions, 307 cells) Any ideas? Thanks, Andreas. ------------------------------------------------------------------------ Andreas Gruenbacher gruenbacher@geoinfo.tuwien.ac.at Research Assistant Phone +43(1)58801-12723 Institute for Geoinformation Fax +43(1)58801-12799 Technical University of Vienna Cell phone +43(664)4064789
Andreas Gruenbacher wrote:
Hello,
I was trying to write an abstraction for bidirectional communication between two threads. For some reason, MVars seem to break:
----------------------------------------------- class Cords c t u where newCord :: IO (c t u) listen :: c t u -> IO t speak :: c t u -> u -> IO ()
data Cord t u = Cord (IO (MVar t)) (IO (MVar u))
instance Cords Cord t u where newCord = return (Cord newEmptyMVar newEmptyMVar) speak (Cord _ s) t = do s' <- s ; putMVar s' t listen (Cord h s) = do h' <- h ; takeMVar h'
otherEnd (Cord t u) = Cord u t
showT :: Cord Int String -> IO () showT cord = do putStrLn "Runnning..." x <- listen cord putStrLn ("Heard " ++ show x) speak cord (show x) putStr ("Said " ++ (show x)) showT cord
main :: IO () main = do cord <- newCord forkIO (showT (otherEnd cord)) speak cord 1 str <- listen cord putStrLn str -----------------------------------------------
You are creating a new MVar with each listen and speak. As a result, the two threads never agree on an MVar, so deadlock occurs. Instead, you should create the pair of MVars in newCord. Try the code below.
import Concurrent
class Cords c t u where newCord :: IO (c t u) listen :: c t u -> IO t speak :: c t u -> u -> IO ()
data Cord t u = Cord (MVar t) (MVar u)
instance Cords Cord t u where newCord = do t <- newEmptyMVar u <- newEmptyMVar return (Cord t u) listen (Cord t _) = takeMVar t speak (Cord _ u) s = putMVar u s
otherEnd (Cord t u) = Cord u t
showT :: Cord Int String -> IO () showT cord = do putStrLn "Runnning..." x <- listen cord putStrLn ("Heard " ++ show x) speak cord (show x) putStrLn ("Said " ++ show x) showT cord
main :: IO () main = do cord <- newCord forkIO (showT (otherEnd cord)) speak cord 1 str <- listen cord putStrLn str
Dean
On Fri, 18 May 2001, Dean Herington wrote:
You are creating a new MVar with each listen and speak. As a result, the two threads never agree on an MVar, so deadlock occurs. Instead, you should create the pair of MVars in newCord. Try the code below.
[...]
Thanks, this works. Thanks! --Andreas.
participants (2)
-
Andreas Gruenbacher -
Dean Herington