我正在写一个小的clojure pub / sub接口。这是非常准确的,只有两种方法可以实际使用:do-pub和sub-listen。 sub-listen采用字符串(子名称),do-pub采用两个字符串(子名称和值)。
我在clojure方面仍然相当新,并且在提出可行的方法时遇到一些麻烦。我的第一个想法(实际上是我的第一个实现)使用了一个包含哈希的代理:
{ subname (promise1 promise2 etc) }
当一个线程想要将它的一个promise对象联合到与它想要的子关联的列表时,然后立即尝试取消引用该promise(因此阻塞)。
当一个pub发生时,它会遍历sub的列表中的每个项目,并将值传递给该项目(promise)。然后它从地图中取消该子名称并将其返回给代理。
通过这种方式,我得到了一个简单的pub子实现工作。然而,问题出现在有人潜水,在一段时间内没有收到酒吧,然后因超时而被杀死。在这种情况下,代理中将存在一个不需要的无价值的承诺,而且如果该子类永远不会被发布,那么这将是内存泄漏的来源。
有没有人对如何解决这个问题有任何想法?或者,如果有更好的方法来做我想要做的整体(我试图避免使用任何外部预先煮熟的pubsub库,这是一个宠物项目而不是一个工作)?
答案 0 :(得分:3)
您可以这样做:
atom
publish
函数将通过传入的值更新原子值到函数add-watch
来通知原子值何时发生变化,即由于调用publish
函数remove-watch
删除订阅。这样你就有了一个非常基本的pub-sub系统。
答案 1 :(得分:3)
我已将Ankur的答案标记为解决方案,但我想稍微扩展一下。我最终做的是拥有一个中心原子,所有客户端线程都在add-watch
上。完成pub后,atom的值将更改为包含sub名称和pub'd值的向量。
客户端传递给add-watch
的函数是部分函数,看起来像
(partial (fn [prom sub key ref _old new] ...) sub prom)
其中,prom是先前生成的承诺。然后客户端在等待该承诺时阻塞。部分函数检查new
中的子信息是否与sub
相同,如果是,则删除监视并使用new
的值传递保证。