首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用forM_时,如何等到TVar完成?

当使用forM_时,如何等到TVar完成?
EN

Stack Overflow用户
提问于 2017-04-28 00:14:58
回答 1查看 226关注 0票数 1

我正在编写一个函数,其中我使用forM_处理一个列表,并将结果附加到一个TVar列表中:

代码语言:javascript
复制
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编译它,结果总是空的。怎么可能等待线程完成呢?我不能使用MVarAsync。我必须使用TVar或其他基于TVar的数据结构来解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-28 02:13:42

惯用的解决方案是使用TMVars:

代码语言:javascript
复制
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 ()

代码语言:javascript
复制
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

在遮罩下,TVar (Maybe a) (so TMVar () ~ TVar (Maybe ()) ~ TVar Bool)与retry是完全等价的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43669931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档