我有两个 MVar(以及一个 MVar 和一个 Chan)。我需要从 Chan 中取出东西并处理它们,直到另一个 MVar 不再为空。我的理想解决方案类似于 UNIX select
函数,我传入一个(可能是空的)MVar 列表和线程阻塞,直到其中一个已满,然后它返回完整的 MVar。尽我所能尝试,除了用 isEmptyMVar 反复轮询每个 MVar 直到我得到错误之外,我想不出任何办法。这似乎效率低下。
一个不同的想法是使用 throwTo,但它会中断线程中发生的一切,我需要以原子方式完成处理 Chan 的工作。
我输入的最后一个想法是为每个尝试读取其 MVar 的 MVar 创建一个新的 forkIO,然后用它自己的实例填充一个新创建的 MVar。然后原始线程可以在该 MVar 上阻塞。 Haskell 线程是否足够便宜,可以运行那么多线程?
最佳答案
Haskell 线程非常便宜,因此您可以通过这种方式解决它,但听起来 STM 更适合您的问题。使用 STM,您可以做到
do var <- atomically (takeTMVar a `orElse` takeTMVar b)
... do stuff with var
由于
retry
的行为和 orElse
,此代码尝试获取 a
,然后如果失败,获取 b
.如果两者都失败,它会阻塞,直到其中任何一个更新并重试。你甚至可以用它来制作你自己的
select
的基本版本。 :select :: [TMVar a] -> STM a
select = foldr1 orElse . map takeTMVar
关于haskell - 一种无需轮询即可在 MVar 上形成 'select' 的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5879128/