2

我正在写一个小 clojure pub/sub 接口。它非常简单,只有两种方法会实际使用:do-pub 和 sub-listen。sub-listen 接受一个字符串(一个子名称),do-pub 接受两个字符串(一个子名称和一个值)。

我对 clojure 还是很陌生,并且在想出一种可行的方法来做到这一点时遇到了一些麻烦。我的第一个想法(实际上也是我的第一个实现)使用了一个包含哈希的单个代理:

{ subname (promise1 promise2 etc) }

当一个线程想要将它 conj 的一个承诺对象添加到与它想要的子关联的列表中时,然后立即尝试取消引用该承诺(因此阻塞)。

当 pub 发生时,它会遍历列表中的每个项目,并将值传递给该项目(承诺)。然后它从映射中解散该子名称并将其返回给代理。

通过这种方式,我得到了一个简单的 pub sub 实现工作。但是,当有人订阅后,问题就出现了,在一定时间内没有收到 pub,然后由于超时而被杀死。在这种情况下,代理中将有一个不需要的毫无价值的承诺,此外,如果该子永远不会被发布,这将是内存泄漏的根源。

有人对如何解决这个问题有任何想法吗?或者,如果有更好的方法来做我想要做的事情(我试图避免使用任何外部预煮的 pubsub 库,这是一个宠物项目而不是一个工作项目)?

4

2 回答 2

3

你可以这样做:

  • 创建一个atom
  • publish函数将通过传入的值更新原子值给函数
  • 订阅者可以使用add-watch原子来通知原子值何时更改,即由于调用publish函数
  • 用于remove-watch删除订阅。

这样,您将拥有一个非常基本的发布-订阅系统。

于 2012-07-13T04:04:38.540 回答
3

我已将 Ankur 的答案标记为解决方案,但我想对其进行一些扩展。我最终做的是拥有一个所有客户端线程都执行的中心原子add-watch。当 pub 完成时,原子的值将更改为包含子名称和要发布的值的向量。

客户端传递给add-watch的函数是一个部分函数,​​看起来像

(partial (fn [prom sub key ref _old new] ...) sub prom)

其中 prom 是先前生成的承诺。然后客户端在等待该承诺时阻塞。部分函数检查 sub innew是否与 相同sub,如果是,则删除手表并使用 from 的值交付承诺new

于 2012-07-13T18:53:24.783 回答