私は STM を使用して作業を行っており、特にTBQueue
データ構造を使用して大きな成功を収めています。TVar
私がそれを使用してきた便利な機能には、基本的に次のように、 a の前提条件に基づいて読み取ることが含まれます。
shouldRead <- readTVar shouldReadVar
if shouldRead
then do
a <- readTBQueue queue
doSomethingWith a
else doSomethingElse
このブロックを実行する前にqueue
が空でshouldReadVar
含まれていると仮定すると、結果として が呼び出され、最初に何が起こっても、要素を含むか含むときにブロックが再実行されます。True
readTBQueue
retry
shouldReadVar
False
queue
この記事(この質問を理解したい場合は読んでください)で説明されている構造と同様の同期チャネル データ構造が必要ですが、前の例のように前提条件で読み取り可能である必要があります。おそらく他のものと一緒に構成することもできます。
操作が定義されたこのデータ構造SyncChan
を呼び出しましょう。writeSyncChan
readSyncChan
そして、考えられるユースケースは次のとおりです: この (疑似) コード (STM/IO の概念が混在しているため、機能しません):
shouldRead <- readTVar shouldReadVar
if shouldRead
then do
a <- readSyncChan syncChan
doSomethingWith a
else doSomethingElse
writeSyncChan
呼び出しで現在ブロックしているスレッドが他にないと仮定すると、 をshouldReadChan
含むか、別のスレッドが をブロックするまで、True
ブロックを " " にしたい。言い換えれば、あるスレッドがオンになり、別のスレッドがブロックに到達したとき、またはその逆の場合、チャネルに沿って値を転送したいのです。それ以外の場合はすべて、読み取りまたは書き込みをキャンセルできるように、両側が の状態にあり、 の変化に反応する必要があります。retry
shouldReadChan
False
writeSyncChan
retry
writeSyncChan
readSyncChan
retry
shouldReadVar
T
上記のリンク先の記事で説明されている 2 つの ( )を使用した単純なアプローチMVar
はもちろん不可能です。データ構造は同期的であるため、2 つのatomically
ブロック内で使用することはできません。これは、1つのブロックを変更して、別のブロックがアトミック コンテキストで変更されるTMVar
のを待つことができないためです。TMVar
代わりに、トランザクションの特定の部分を「コミット」し、特定の変数が変更されたときにのみロールバックでき、他の変数は変更できない、一種の部分的な原子性を探しています。上記の記事の最初の例のように「msg」変数と「ack」変数がある場合、「msg」変数に書き込み、値が「ack」に到着するのを待つか、変更する他のトランザクション変数。他のトランザクション変数が変更された場合、アトミック ブロック全体が再試行され、「ack」値が到着した場合、トランザクションは以前の状態のまま続行されます。読み取り側についても、同様のことが起こるはずですが、もちろん "msg" から読み取り、"ack" に書き込みます。
GHC STM を使用してこれを行うことは可能ですか、または手動で MVar/ロールバック処理を行う必要がありますか?