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

欢迎!请查看关于页面以获取更多关于如何使用本网站的信息。

+2
core异步
  • 每次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?的定义进行澄清,以支持这种新情况。在Clojure中,realized?的其他所有用法都保证后续deref将立即填充,但这对于通道来说不会是事实,如果另一个消费者取走该值。

一旦解决这个问题,我需要在审查之前对core.async实现协议有更好的文档字符串。使用线程的保证是什么?工作在哪里排队,如果队列满了会发生什么?
0

由 alexmiller 发表的评论:

我实现的 realized? 依赖于 Rich 对你的问题的回答(来自内部聊天):"open+empty = false, else true",并且我认为这正是实施和反映在测试中的内容。这也比我仅仅在关闭时实现的意义大。

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

你能更具体一点说明是哪种实现协议吗?我猜你具体指的是 Channel 和 Buffer。任何线程都可能调用 Channel。M2MC 使用互斥量保护其内部状态,并将调用传递到 Buffer。所有对 buffer 的调用都由 channel 互斥量保护。M2MC 在 puts 和 takes 列表中排序列为即将到来的 puts 和 takes。这些受固定限制 clojure.core.async.impl.protocols/MAX-QUEUE-SIZE (1024) 的约束,在这点上将抛出异常。

0

由 alexmiller 发表的评论:

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

`
(deftype ManyToManyChannel
#_existing_code...
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,因此这里存在循环依赖问题。处理 <!! 和 timeouts 相对简单,可以通过查找 delay 后的 var 如此实现

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

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

然而,我在如何处理 do-alt 和 alts(image: ) 的宏 alt!! 方面感到有些困惑。

0

由 gshayban 发表的评论:

不要依赖解决循环依赖。相反,创建一个共享的 alt-flag,并将两个处理器(link: 1)排队。fret 会提供承诺,然后 deref 这个承诺。

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

0

由 alexmiller 发表的评论:

新补丁回到了预前的 blocking deref 实现(基本上是 <!! 的主体),并添加了以 alts 为基础的新 timed deref 版本。

0

评论人:fogus

然而,我在如何使用alt!!实现等效操作上有些困惑
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](https://clojure.atlassian.net/browse/ASYNC-102)(由stu报告)
...