请在 2024 年 Clojure 状态调查! 分享您的想法。

欢迎!请参阅 关于 页面以了解更多关于它是如何工作的信息。

+2
core.async
  • 每次 deref 会从 channel 中获取一个值
  • 从已关闭的 channel 中 deref 返回 nil
  • 带超时的 deref 必须要么超时,要么从 channel 中取值(两者不可兼得!)。可能只需要通过 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 与描述 "当 channel 关闭时变为 realized" 不符 —— 而是channel 有可用的值时变为 realized。对我来说,这两种解释都似乎有问题,我认为需要对 {{realized?}} 的定义进行澄清,以支持这种新的情况。Clojure 中 {{realized?}} 的其他用途都保证后续的 deref 将立即填充,但如果另一个消费者获取了值,这就不适用于 channels。

一旦解决这个问题,我可以在筛选此内容之前为 core.async 实施协议提供更好的文档字符串。关于线程的使用有哪些保证?工作将排队在哪里,队列满时会发生什么?
0

评论者:alexmiller

我的对“实现”的实现在于Rich对你问题的回答(内部聊天):”空+开 = false,否则真”,我相信这些都是已经实现的并且在测试中得到反映。这一点比我只关注关闭时实现更有意义。

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

你能更具体地说明哪个实现协议吗?我猜你指的是信道和缓冲区。任何线程都可以调用信道。M2MC通过互斥锁保护其内部状态,并将调用转发到缓冲区。所有缓冲区调用都受到信道互斥锁的保护。M2MC将挂起的put和take操作入队到put和take列表中。这些操作由固定极限clojure.core.async.impl.protocols/MAX-QUEUE-SIZE(1024)限制,此时会抛出异常。

0

评论者:alexmiller

在多对多信道上使用现有的异步结构实现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依赖于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将传递一个承诺,然后 deref 该承诺。

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

0

评论者:alexmiller

新补丁回归到之前阻塞deref的实现(即<!!的内部结构),并添加了基于alts的时间deref新版本。

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
...