[英]How to wait until forM_ finishes, when using TVar?
I'm writing a function, where I process a list using forM_
, and append the result to a TVar
list: 我正在编写一个函数,我使用
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
The result is always empty, if I compile it with -threaded
. 如果我用
-threaded
编译它,结果总是为空的。 How is it possible to wait for the threads to finish? 怎么可能等待线程完成? I can not use
MVar
or Async
. 我不能使用
MVar
或Async
。 I have to solve this problem using TVar
, or other data structures which are based on TVar
我必须使用
TVar
或其他基于TVar
数据结构来解决这个问题
The idiomatic solution would be to use TMVar
s: 惯用的解决方案是使用
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
but if you are really only allowed to use TVar
s, you can simulate a TMVar ()
with a TVar Bool
: 但如果您真的只允许使用
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
Under the hood, TMVar a
is just a TVar (Maybe a)
(so TMVar ()
~ TVar (Maybe ())
~ TVar Bool
) with takeTMVar
doing a readTVar
and a retry
, so the above two solutions are operationally completely equivalent. 在引擎盖下,
TMVar a
只是一个TVar (Maybe a)
(所以TMVar ()
~ TVar (Maybe ())
~ TVar Bool
)带有takeTMVar
做一个readTVar
和retry
,所以上面两个解决方案在操作上是完全等效的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.