2

私は小さなclojurepub/subインターフェースを書いています。これは非常に必要最低限​​のものであり、実際に使用されるのはdo-pubとsub-listenの2つの方法だけです。sub-listenは文字列(サブ名)を取り、do-pubは2つの文字列(サブ名と値)を取ります。

私はまだclojureにかなり慣れていないので、これを実行する方法を考え出すのに問題があります。私の最初の考え(そして実際に私の最初の実装)は、ハッシュを保持する単一のエージェントを使用します:

{ subname (promise1 promise2 etc) }

スレッドがsubを実行したい場合、conjはpromiseオブジェクトを、必要なsubに関連付けられたリストに追加し、すぐにそのpromiseの参照を解除しようとします(したがってブロックします)。

パブが発生すると、サブのリスト内のすべてのアイテムを調べて、そのアイテムに値を提供します(約束)。次に、そのサブネームをマップから分離し、エージェントに返します。

このようにして、単純なpubサブ実装が機能するようになりました。ただし、問題は、誰かがサブスクライブし、一定時間パブを受け取らなかった後、タイムアウトのために殺された場合に発生します。このシナリオでは、エージェントに必要のない無価値な約束があり、さらに、そのサブが公開されない場合、これはメモリリークの原因になります。

誰かがこれを解決する方法について何か考えがありますか?または、私が全体的にやろうとしていることを行うためのより良い方法がある場合(外部の事前に作成されたpubsubライブラリの使用を避けようとしているので、これはペットプロジェクトであり、機能するものではありません)?

4

2 に答える 2

3

あなたはこのようなことをすることができます:

  • 作成するatom
  • publish関数は、関数に渡された値によってアトム値を更新します
  • サブスクライバーはadd-watch、アトムを使用して、アトム値が変更されたとき、つまりpublish関数の呼び出しによって通知を受けることができます。
  • remove-watchサブスクリプションを削除するために使用します。

このようにして、非常に基本的なpub-subシステムが作成されます。

于 2012-07-13T04:04:38.540 に答える
3

私はAnkurの答えを解決策としてマークしましたが、それを少し拡張したいと思いました。私がやったことは、すべてのクライアントスレッドが実行する中心的なアトムを持つことですadd-watch。パブが完了すると、アトムの値は、サブの名前とパブされる値を含むベクトルに変更されます。

クライアントが渡す関数add-watchは、次のような部分関数です。

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

ここで、promは以前に生成されたpromiseです。次に、クライアントはその約束を待っている間ブロックします。部分関数は、sub innewがと同じかどうかをチェックします。同じsubである場合は、ウォッチを削除し、からの値でpromiseを実行しますnew

于 2012-07-13T18:53:24.783 に答える