
Suppose that a program using the Control.Concurrent.STM module had a producer/consumer setup - one thread writing to a channel, the other thread reading from the channel. It seems natural to want a function that the producer can call that will block until the consumer has finished consuming everything currently in the channel. The way I first tried implementing this was: -- types simplified for this example flush :: TChan () -> STM () flush chan = do e <- isEmptyTChan if not e then retry else return () Used in isolation, i.e. atomically $ writeTChan chan () atomically $ flush chan it works fine. However, when composed (atomically $ writeTChan chan () >> flush chan), it causes a race condition, usually resulting in deadlock, as the "retry" in flush replays the call to writeTChan as well. This situation begs for a way to limit the scope of "retry", in which case flush would be: flush chan = limitRetry $ do e <- isEmptyTChan if not e then retry else return () Abe

On Thu, Apr 21, 2005 at 10:47:27AM -0400, Abraham Egnor wrote:
Used in isolation, i.e.
atomically $ writeTChan chan () atomically $ flush chan
it works fine. However, when composed (atomically $ writeTChan chan () >> flush chan), it causes a race condition, usually resulting in deadlock, as the "retry" in flush replays the call to writeTChan as well.
As long as you are in this transaction nobody will get from chan the element you just put there. Before the transaction commits, for the outside world it's like you've never called writeTChan. But inside the transaction you see a chan with an element that you've just written there. So within this transaction the chan has no chance to be emptied (unless you emptied it yourself). No point in waiting. As you say, it works in isolation. Use it this way. Best regards Tomasz

Hello Abraham, Thursday, April 21, 2005, 6:47:27 PM, you wrote: AE> Suppose that a program using the Control.Concurrent.STM module had a AE> producer/consumer setup - one thread writing to a channel, the other AE> thread reading from the channel. It seems natural to want a function AE> that the producer can call that will block until the consumer has AE> finished consuming everything currently in the channel. i think this is a bad programming technique. it's better to use another discipline of managing queue. for example, in my program i just allocate fixed number of buffers and use them to send data over channel. as a result, channel can't contaion more than this nu,ber of elements. if you will say more about your GOAL, not particular decision you made, may be i can suppose you better solution -- Best regards, Bulat mailto:bulatz@HotPOP.com
participants (3)
-
Abraham Egnor
-
Bulat Ziganshin
-
Tomasz Zielonka