haskell - 一种无需轮询即可在 MVar 上形成 'select' 的方法

标签 haskell concurrency transactional-memory

我有两个 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/

相关文章:

haskell - 函数类型限制

haskell - STM单子(monad)问题

haskell - 使用依赖类型语言进行编程时,我们如何克服编译时间和运行时差距?

haskell - 无法理解列表推导式

java - ExecutorService awaitTermination 方法未按预期执行

java - 同步多个异步请求

haskell - Clojure、Haskell(和其他语言)在 STM 中使用了哪些算法?

c++ - 为什么在使用 GCC 7、libstdc++ 和 -fgnu-tm 编译时,std::is_function 无法识别 transaction_safe 函数?

haskell - 在 Haskell 的 Aeson 中省略 Nothing/null 字段

java - 从它自己的构造函数启动一个线程是个好主意吗?