質問

私には2つのmvarがあります(まあmvarとchan)。私はチャンから物事を引き出して、他のmvarがもう空にならないまでそれらを処理する必要があります。私の理想的な解決策は、Unixのようなものです select (おそらく空の)MVARのリストを渡し、スレッドが1つがいっぱいになるまでブロックする関数で、完全なMVARを返します。私が虚偽になるまで、それぞれのMVARをisEmptymvarで繰り返し投票することを超えて、これを行う方法を考えないかもしれません。これは非効率的なようです。

別の考えはThrowToを使用することでしたが、スレッドで起こっていることを中断し、原子的にチャンを処理する必要があります。

私がタイピングしているときの最後の考えは、MVARを読み、新しく作成したMVARを独自のインスタンスで埋めようとする各MVARに新しいForkioを作成することです。元のスレッドは、そのMVARでブロックできます。 Haskellスレッドは、それほど多くのことを実行するのに十分な安いですか?

役に立ちましたか?

解決

Haskellスレッドは非常に安いので、そのように解決することができますが、STMは問題により適しているようです。 STMを使用すると、できます

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

の行動のため retryorElse, 、このコードは取得しようとします a, 、それが失敗した場合、取得します b. 。両方が失敗した場合、それらのいずれかが更新され、再び試行されるまでブロックします。

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

select :: [TMVar a] -> STM a
select = foldr1 orElse . map takeTMVar

他のヒント

STMバージョンを使用してみませんか、 TChanTVar, 、 とともに retryorElse 行動?

Selectの実装は、STMの素晴らしい機能の1つです。 「Composable Memory Transactions」から:

これを超えて、Orelseも提供します。これにより、代替品として構成できるため、最初の再試行の場合は2番目のものが実行されます(セクション3.4)。この機能により、Unix Select System Callのように、スレッドは一度に多くのことを待つことができます。


ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top