2012-07-13 128 views
2

我正在写一个小clojure pub/sub界面。它非常准确,只有两种实际使用的方法:do-pub和sub-listen。子侦听需要一个字符串(一个子名),do-pub需要两个字符串(一个子名和一个值)。Clojure:需要架构建议

我在clojure还是比较新的,并且遇到了一些麻烦,想出了一个可行的方法来做到这一点。我首先想到的(实际上是我的第一个执行)使用其持有的哈希单一代理:

{ subname (promise1 promise2 etc) } 

当一个线程要分呢连词是一个承诺对象就是了子相关联的列表,然后立即尝试取消引用该承诺(因此阻止)。

当一个酒吧发生时,它会遍历该列表中的每个项目并将该值传递给该项目(承诺)。然后它从地图中解析出该子名并将其返回给代理。

以这种方式,我得到了一个简单的酒吧子实现工作。但是,如果有人下潜,在一段时间内没有收到酒吧,则会因为超时而被杀。在这种情况下,代理中会有一个不值钱的承诺,而且如果该子从不被发布,这将成为内存泄漏的来源。

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

回答

3

你可以做这样的事情:

  • 创建​​
  • publish功能会更新的值传递给函数
  • 认购原子值可以使用add-watch上的原子是通知原子值何时发生变化,即由于致电publish函数
  • 使用remove-watch删除订阅。

这样你就会有一个非常基本的pub-sub系统。

3

我已经标记了Ankur的答案作为解决方案,但我想稍微扩展一下。我最终做的是拥有一个中心原子,所有客户端线程开启add-watch。当一个pub被完成时,atom的值被改变为一个包含sub的名字和被发布的值的向量。

客户端传递给add-watch的功能是一个局部函数看起来像

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

其中PROM是先前产生的一个承诺。客户在等待承诺时阻塞。部分函数检查new中的子项是否与sub相同,如果是,则删除手表并从new开始执行承诺。