Gre*_*con 7 concurrency multithreading haskell chat
Simon Marlow在Haskell eXchange 2012上发表了高性能并发演讲.由于时间限制,他跳过了一个简单的并发聊天服务器上的部分.对于省略的内容感到好奇,网络搜索在服务器应用程序上找到了类似的幻灯片,并在GitHub上找到了一个实现.
幻灯片33读取
回去谈谈......
Run Code Online (Sandbox Code Playgroud)talk :: Server -> Handle -> IO () talk server@Server{..} handle = do hSetNewlineMode handle universalNewlineMode hSetBuffering handle LineBuffering readName where readName = do hPutStrLn handle "What is your name?" name <- hGetLine handle m <- checkAddClient server name handle case m of Nothing -> do hPrintf handle "The name %s is in use" name readName Just client -> do runClient server client `finally` removeClient server name严格地说,我们应该堵塞的孔
checkAddClient和finally(见注释...)
早些时候,幻灯片3提到"笔记中的第14章",我认为这是他即将出版的书.什么是checkAddClient和之间的同步裂缝finally,以及我们如何插入它?
上述实现使用maskControl.Exception.如果这是修复,那么一个不合时宜的异常会破坏聚会的场景是什么?
Run Code Online (Sandbox Code Playgroud)... readName = do hPutStrLn handle "What is your name?" name <- hGetLine handle if null name then readName else mask $ \restore -> do ok <- checkAddClient server name handle case ok of Nothing -> restore $ do hPrintf handle "The name %s is in use, please choose another\n" name readName Just client -> restore (runClient server client) `finally` removeClient server name
您要确保每个成功的项目都checkAddClient与removeClient. finally底部的语句仅保证在操作开始removeClient时运行runClient。
但是,在代码可以接收异步异常的结束checkAddClient和开始之间有一个短暂的窗口。runClient如果这样做,finally将没有机会注册该removeClient命令。这就是西蒙所说的同步裂缝。
解决方案是默认屏蔽异步异常,只允许它们出现在某些地方(即由 包裹的操作restore)。这密封了上述裂缝。