[英]How to wait until forM_ finishes, when using TVar?
我正在編寫一個函數,我使用forM_
處理列表,並將結果附加到TVar
列表:
import Control.Concurrent.STM
import Control.Concurrent.STM.TVar
import Control.Concurrent (forkIO)
import Control.Monad (forM_)
insert :: a -> [a] -> [a]
insert = (:) -- stub
my_func_c :: (a -> a) -> [a] -> IO [a]
my_func_c my_function arr = do
res_var <- atomically $ newTVar ([]::[a])
forkIO $ forM_ arr $ \x -> atomically $ do
let y = id $! my_function x
modifyTVar res_var (insert y)
atomically $ readTVar res_var
如果我用-threaded
編譯它,結果總是為空的。 怎么可能等待線程完成? 我不能使用MVar
或Async
。 我必須使用TVar
或其他基於TVar
數據結構來解決這個問題
慣用的解決方案是使用TMVar
:
my_func_c :: (a -> a) -> [a] -> IO [a]
my_func_c my_function arr = do
res_var <- atomically $ newTVar []
finished <- atomically $ newEmptyTMVar
forkIO $ do
forM_ arr $ \x -> atomically $ do
let y = id $! my_function x
modifyTVar res_var (insert y)
atomically $ putTMVar finished ()
atomically $ takeTMVar finished >> readTVar res_var
但如果您真的只允許使用TVar
,您可以使用TVar Bool
模擬TMVar ()
:
my_func_c :: (a -> a) -> [a] -> IO [a]
my_func_c my_function arr = do
res_var <- atomically $ newTVar []
finished <- atomically $ newTVar False
forkIO $ do
forM_ arr $ \x -> atomically $ do
let y = id $! my_function x
modifyTVar res_var (insert y)
atomically $ writeTVar finished True
atomically $ waitTVar finished >> readTVar res_var
waitTVar :: TVar Bool -> STM ()
waitTVar tv = do
finished <- readTVar tv
unless finished retry
在引擎蓋下, TMVar a
只是一個TVar (Maybe a)
(所以TMVar ()
~ TVar (Maybe ())
~ TVar Bool
)帶有takeTMVar
做一個readTVar
和retry
,所以上面兩個解決方案在操作上是完全等效的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.