14

私は 2 つの MVar (MVar と Chan) を持っています。Chan から何かを取り出して、他の MVar が空でなくなるまで処理する必要があります。私の理想的な解決策は、(おそらく空の) MVar とスレッド ブロックのリストを渡す UNIX 関数のようなものselectで、そのうちの 1 つがいっぱいになると、完全な MVar が返されます。false になるまで、isEmptyMVar を使用して各 MVar を繰り返しポーリングする以外に、これを行う方法は考えられません。これは効率が悪いようです。

別の考えでは、throwTo を使用することでしたが、それはスレッドで起こっていることを中断し、Chan からアトミックな方法でジョブの処理を完了する必要があります。

私が入力している最後の考えは、MVar を読み取ろうとする各 MVar に対して新しい forkIO を作成し、新しく作成された MVar を独自のインスタンスで埋めようとすることです。その後、元のスレッドはその MVar でブロックできます。Haskell スレッドはそれほど多く実行できるほど安価ですか?

4

2 に答える 2

16

Haskell スレッドは非常に安価なので、その方法で解決できますが、問題には STM の方が適しているように思えます。STMでできること

do var <- atomically (takeTMVar a `orElse` takeTMVar b)
   ... do stuff with var

retryとの動作のためorElse、このコードは を取得しようとしa、失敗した場合は を取得しますb。両方とも失敗した場合、どちらかが更新されるまでブロックされ、再試行されます。

これを使用して、独自の初歩的なバージョンを作成することもできますselect

select :: [TMVar a] -> STM a
select = foldr1 orElse . map takeTMVar
于 2011-05-04T05:59:38.723 に答える
12

STMバージョン、TChanおよびTVarretryおよびのorElse動作を使用するのはどうですか?

selectの実装は、STMの優れた機能の1つです。「コンポーザブルメモリトランザクション」から:

これに加えて、orElseも提供します。これにより、それらを代替として構成できるため、最初の再試行で2番目が実行されます(セクション3.4)。この機能により、スレッドはUnix selectシステムコールのように一度に多くのことを待つことができます。ただし、orElseは適切に構成されますが、selectはそうではありません。


于 2011-05-04T06:00:51.697 に答える