RE: Question about 'Tackling the Awkward Squad'
This is probably superfluous now but I still don't understand Hugs' behaviour. I ran the following with ghc 4.08.1: module Main(main) where import Concurrent main = do chan <- newChan writeChan chan "One" dup <- dupChan chan writeChan chan "Two" x <- readChan dup y <- readChan chan z <- readChan chan putStrLn (x++y++z) I expected the answer "TwoOneTwo" but instead got $ ./main d:\dom\hugs98\concurrent\main.exe: no threads to run: infinite loop or deadlock? which confirmed the problem that Don highlighted. With Hugs I got the following: Main> main (232 reductions, 458 cells) which was puzzling. I'm running Version: May 1999 with -98. Dominic. simonpj@microsoft.com on 28/01/2001 11:18:00 To: don_wakefield haskell cc: bcc: Dominic Steinitz Subject: RE: Question about 'Tackling the Awkward Squad' Don Crumbs! You're right! The MVars that are drawn as heavy black boxes in Figure 7 of Tackling the Awkward Squad are used to block the consumer when it catches up with the producer. But if there is more than one consumer, it's not OK to leave these MVars empty. Instead, getChan should do a put after its take; or, more elegantly, should use readMVar, which has the semantics of take-followed-by-put: getchan (read, write) = do { head_var <- takeMVar read ; MkItem val new_head <- readMVar head_var ; putMVar read new_head ; return val } Concurrent programming is tricky. I owe you a beer! I'll fix the version on the Web Simon | when I ran across what appears to be an error. On page 34, while | discussing Channels, he proposes a function called dupChan: | | dupChan (read, write) | = do { new_read <- newEmptyMVar ; | hole <- takeMVar write ; | putMVar write hole ; | putMVar new_read hole ; | return (new_read, write) } | | The rationale is given thusly: | | "For example, consider a multi-cast channel, in which there are | multiple readers, each of which should see all the values written to | the channel ... The idea is that the channel returned by dupChan can | be read independently of the original, and sees all (and only) the | data written to the channel after the dupChan call." | | But earlier he has defined getChan thusly: | | getchan (read, write) | = do { head_var <- takeMVar read ; | MkItem val new_head <- takeMVar head_var ; | putMVar read new_head ; | return val } | | Since the line which performs the 'takeMVar head_var' leaves the MVar | referenced by head_var empty, the dupChan 'new_read' Stream | should block | when the reader tries to *also* use getChan on this Stream, isn't this | so? Am I missing some subtlety? I drew all the pictures :^)~ | | -- | Don Wakefield Mentor Graphics Corporation | (503) 685-1262 8005 S.W. Boeckman Road | don_wakefield@mentorg.com Wilsonville, OR 97070-7777 | | _______________________________________________ | Haskell mailing list | Haskell@haskell.org | http://www.haskell.org/mailman/listinfo/haskell | _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell ------------------------------------------------------------------------------------------------- 21st century air travel http://www.britishairways.com
participants (1)
-
Steinitz, Dominic J