简体   繁体   English

使用TVar时如何等待M_完成?

[英]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 . 我不能使用MVarAsync 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做一个readTVarretry ,所以上面两个解决方案在操作上是完全等效的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM