0
我这是为了实现一些基于STM-队列以下Haskell代码:我在STM上被阻塞的确切原因是什么?
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Concurrent.Async
import Control.Concurrent.STM
import Control.Exception
import Control.Monad (forever)
import Hevents.Eff
import System.IO
withStore :: (FileStorage -> IO a) -> IO a
withStore = bracket (openFileStorage "test.store") closeFileStorage
data Op = Op String (TMVar Int)
storerun :: TBQueue Op -> IO()
storerun q = do
h <- openFile "store.test" ReadWriteMode
hSetBuffering h NoBuffering
forever $ do
Op s v <- atomically $ readTBQueue q
hPutStrLn h s
atomically $ putTMVar v (length s)
main :: IO()
main = do
q <- newTBQueueIO 100
_ <- async $ storerun q
storeInput q
where
storeInput q = forever $ do
putStrLn "pushing"
l <- getLine
v <- newEmptyTMVarIO
r <- atomically $ do
writeTBQueue q (Op l v)
takeTMVar v
putStrLn $ "got " ++ show r
当运行这个代码引发一个BlockedIndefinitelyOnSTM
例外。如果我将storeInput
函数更改为以下内容:
storeInput q = forever $ do
putStrLn "pushing"
l <- getLine
v <- atomically $ do
v <- newEmptyTMVar
writeTBQueue q (Op l v)
return v
r <- atomically $ takeTMVar v
putStrLn $ "got " ++ show r
程序运行良好。
我对什么会导致此异常的理解是,STM事务中涉及的变量已以某种方式被垃圾收集,仅在单个线程中可见,并且因此被锁定,因为事务变量的内容获胜永远不会改变。
在我的代码中,在Op
结构中的变量在一个线程中创建,使用事务性队列传递给另一个线程,然后由另一个线程使用,并且似乎没有理由使其成为垃圾回收收集在任何线程。
因此,我不清楚为什么这个代码是失败的。
当然。我似乎总是忘记...... – insitu