Clojure 2024 年状态调查 中分享您的想法!

欢迎!请参阅 关于 页面以了解有关其工作方式的更多信息。

+2
core.async
  • 每次 deref 都会从通道中获取一个值
  • 从已关闭的通道 deref 返回 nil
  • 带有超时的 deref 必须要么超时,要么从通道中获取值(不能两者同时)。可能需要通过 var 调用 alt!! 的某个变体。
  • 高效利用内部方法
  • 不要实现 IPending/realized,这两种解释都不是很好

补丁: async-102-2.patch

deref 和定时 deref 的实现是(链接:http://dev.clojure.org/jira/browse/ASYNC-102?focusedCommentId=37211&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-37211 文本:概念上简单),但由于循环命名空间依赖项难以实现。欢迎提出建议。

8 答案

0
_评论者:stu_

async-102.patch 与描述 "通道关闭时变为 realized" 不符 - 而是通道有可用值时变为 realized。两种解释对我来说都似乎有问题,我认为需要澄清 {{realized?}} 的定义以支持这种情况。Clojure 中其他 {{realized?}} 的使用都保证了后续 deref 将立即填充,但如果另一个消费者取走该值,则对于通道来说这将不会成立。

解决这个问题后,我需要在审查这可能需要更好地为 core.async 实现协议提供文档字符串。关于线程的使用有什么保证?工作在哪里排队,如果队列满了会发生什么?
0

评论者:alexmiller

我对realized的实现基于Rich对你的问题的回答(来自内部聊天):"open+empty = false, else true",我相信这就是实现,并在测试中得到了反映。这对我来说比仅在关闭时实现更加合理。

你的评论与realized的其他情况似乎准确,所以我同意这是一个问题。

你能更具体地说明哪种实现协议吗?我猜你特指的是Channel和Buffer。任何线程都可能调用Channel。M2MC使用互斥锁保护其内部状态,并将调用传递到Buffer。所有对缓冲区的调用都由通道互斥锁保护。M2MC将在puts和takes列表中入队挂起的puts和takes。这些受限于固定的上限clojure.core.async.impl.protocols/MAX-QUEUE-SIZE(1024),在此点上会抛出异常。

0

评论者:alexmiller

使用现有的async结构在ManyToManyChannel上实现IDeref和IBlockingDeref的概念性实现相对简单

`
(deftype ManyToManyChannel
...
IDeref
(deref [this] (<!! this))

IBlockingDeref
(deref [this ms timeoutValue]

(alt!!
  this ([val _] val)
  (timeout ms) timeoutValue)))

`

然而,M2MC在clojure.core.async.impl.channels中定义。<!!, alt(image: ), 和timeout都定义在clojure.core.async中,它依赖于clojure.core.async.impl.channels,因此这里存在循环依赖问题。解决这个问题的方法类似于查找delay后的var:

`
(def ^:private <!!' (delay (find-var 'clojure.core.async/<!!)))

;; 然后
IDeref
(deref [this] (@<!!' this))
`

但是,我有点不清楚如何处理类似alt!!的情况,它是do-alt和alts(image: )的宏。

0

评论者:gshayban

不要依赖于解决循环依赖。相反,创建一个共享的alt标志,并将两个处理器排队(链接:1)。fret将发送一个承诺,然后解析承诺。

(链接:1) https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L230-L231

0

评论者:alexmiller

新补丁返回到之前的阻塞引用实现版本(基本是 <!!> 的核心内容)并添加了一个基于 alts 的新定时引用版本。

0

评论由:fogus 发表

然而,我有点难以理解如何用
alt!!(一个围绕 do-alt 和 alts!! 的宏)来做等效的操作。

我想知道以下内容是否可以解决 alts!! 的问题

(def ^:private ^:macro alts!!' (deref (find-var 'clojure.core.async/alts!!)))

然后在 IBlockingDeref 的 deref 实现中使用它。目前,由于它使用了某些 core.async 实现细节(实际上就是同样的代码),因此很难理解所写的代码。而你的 IBlockingDeref.deref 实现则非常清晰,然而由于循环依赖而被启发出的实现则相对不那么清晰。不要过分强调这一点(尽管我似乎总是这样做),alts!! 是对这个问题的明确实现,但使用它的核心内容会使问题复杂化。如果我可以决定,我会更喜欢可读性。

话虽如此,作为一个人类宏展开器,我还是最终推理出了实现的逻辑。

0

评论者:alexmiller

这似乎不太奏效。如果您有其他有效的方案,那将是非常棒的!

0
参考资料: https://clojure.atlassian.net/browse/ASYNC-102(由 stu 报告)
...