一种形成“选择”的方法无需轮询即可查看 MVar

发布于 2024-11-04 22:48:22 字数 422 浏览 5 评论 0原文

我有两个 MVar(一个 MVar 和一个 Chan)。我需要从 Chan 中取出东西并处理它们,直到另一个 MVar 不再为空。我理想的解决方案类似于 UNIX select 函数,其中我传入一个(可能是空的)MVar 列表,并且线程会阻塞,直到其中一个已满,然后返回完整的 MVar。尽我所能,除了用 isEmptyMVar 反复轮询每个 MVar 直到出现错误为止,我想不出有什么办法可以做到这一点。这看起来效率很低。

另一个想法是使用 throwTo,但它会中断线程中正在发生的事情,我需要以原子方式完成 Chan 中的作业处理。

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

I have two MVars (well an MVar and a Chan). I need to pull things out of the Chan and process them until the other MVar is not empty any more. My ideal solution would be something like the UNIX select function where I pass in a list of (presumably empty) MVars and the thread blocks until one of them is full, then it returns the full MVar. Try as I might I can think of no way of doing this beyond repeatedly polling each MVar with isEmptyMVar until I get false. This seems inefficient.

A different thought was to use throwTo, but it interrupts what ever is happening in the thread and I need to complete processing a job out the the Chan in an atomic fashion.

A final thought as I'm typing is to create a new forkIO for each MVar which tries to read its MVar then fill a newly created MVar with its own instance. The original thread can then block on that MVar. Are Haskell threads cheap enough to go running that many?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不必在意 2024-11-11 22:48:22

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 threads are very cheap, so you could solve it that way, but it sounds like STM would be a better fit for your problem. With STM you can do

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

Because of the behavior of retry and orElse, this code tries to get a, then if that fails, get b. If both fail, it blocks until either of them is updated and tries again.

You could even use this to make your own rudimentary version of select:

select :: [TMVar a] -> STM a
select = foldr1 orElse . map takeTMVar
み青杉依旧 2024-11-11 22:48:22

如何使用 STM 版本、TChanTVar 以及 retryorElse 行为?

实现 select 是 STM 的一项出色功能。来自“可组合内存事务”:

除此之外,我们还提供orElse,
这使得它们可以作为替代品组成,这样
如果第一次重试,则运行第二个(第 3.4 节)。这种能力允许线程同时等待许多事情,比如
Unix select 系统调用 – 除了 orElse 组合得很好,
而 select 则不然。


How about using STM versions, TChan and TVar, with the retry and orElse behavior?

Implementing select is one of STM's nice capabilities. From "Composable Memory Transactions":

Beyond this, we also provide orElse,
which allows them to be composed as alternatives, so that
the second is run if the first retries (Section 3.4). This ability allows threads to wait for many things at once, like the
Unix select system call – except that orElse composes well,
whereas select does not.


~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文