我有两个MVar(一个MVar和一个Chan)。我需要从Chan中拉出东西并进行处理,直到另一个MVar不再为空。我理想的解决方案是使用UNIX select函数之类的方法,在该函数中,我传入(可能为空)MVar和线程块的列表,直到其中一个已满,然后返回完整的MVar。尽我所能尝试,除了重复使用isEmptyMVar轮询每个MVar,直到我得到错误为止,我想不出任何办法。这似乎效率低下。

另一种想法是使用throwTo,但是它中断了线程中发生的一切,我需要以原子方式完成处理Chan的作业。

我输入时的最后一个想法是为每个MVar创建一个新的forkIO,尝试读取其MVar,然后用其自己的实例填充新创建的MVar。然后,原始线程可以在该MVar上阻塞。 Haskell线程便宜到足以运行那么多线程吗?

最佳答案

Haskell线程非常便宜,因此您可以通过这种方式解决,但听起来STM更适合您的问题。使用STM,您可以

do var <- atomically (takeTMVar a `orElse` takeTMVar b)
   ... do stuff with var

由于retryorElse的行为,此代码尝试获取a,如果失败,则获取b。如果两者均失败,它将阻塞直到其中任何一个更新并重试。

您甚至可以使用它来制作自己的select的基本版本:
select :: [TMVar a] -> STM a
select = foldr1 orElse . map takeTMVar

关于haskell - 一种无需轮询即可在MVar上形成'select'的方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5879128/

10-15 23:55