作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想选择性地中止 getChar
行动。我需要以下功能:
getChar' :: (Char -> IO ()) -> IO (IO ())
如果是abort <- getChar' callback
,从标准输入读取字符,除非 abort
在角色可用之前调用。如果读取一个字符,callback
用它来调用。
我有以下原型(prototype)实现:
import Control.Monad
import Control.Concurrent
getChar' :: (Char -> IO ()) -> IO (IO ())
getChar' callback = do
v <- newEmptyMVar
tid <- forkIO $ do
c <- getChar
b <- tryPutMVar v ()
when b $ callback c
return $ do
b <- tryPutMVar v ()
when b $ killThread tid
问题是 killThread
可能会在读取字符后但在放置 ()
之前中止线程进入 MVar。
我不知道如何解决这个问题,基础包有可能吗?如果没有,您是否在其他包中看到过类似的功能?
最佳答案
我认为实现此目的最简单的方法是执行您自己的缓冲。这是一个简单的原型(prototype)。它假设您在程序中只调用一次 launchIOThread
。它不处理 EOF 或其他 IO 异常,但这应该很容易。
import Control.Concurrent
import Control.Concurrent.STM
import Data.Maybe
import Control.Monad
type Buffer = TVar (Maybe Char)
launchIOThread :: IO Buffer
launchIOThread = do
buf <- atomically $ newTVar Nothing
_ <- forkIO $ ioThread buf
return buf
ioThread :: Buffer -> IO ()
ioThread buf = loop where
loop =
join $ atomically $ do
contents <- readTVar buf
if isJust contents -- no-one has taken the character yet
then retry -- relax
else return $ do
c <- getChar
atomically $ writeTVar buf (Just c)
loop
getChar' :: Buffer -> (Char -> IO ()) -> IO (IO ())
getChar' buf callback = do
abortFlag <- atomically $ newTVar False
_ <- forkIO $ doGetChar abortFlag
return $ atomically $ writeTVar abortFlag True
where
doGetChar abortFlag = join $ atomically $ do
mbC <- readTVar buf
abort <- readTVar abortFlag
case mbC of
Just c ->
do writeTVar buf Nothing; return $ callback c
Nothing | abort -> return $ return ()
_ -> retry
关于haskell - 如何安全地中止 getChar?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16769579/
我是一名优秀的程序员,十分优秀!