
Hi Paolino, You wrote:
I have a doubt that this code works like I want because actual STM implementation exposes its effects
import Control.Concurrent import Control.Concurrent.STM
main = do c <- atomically $ newTChan :: IO (TChan ()) r <- atomically $ newTVar False forkIO $ do atomically $ do r0 <- readTVar r case r0 of True -> return () False -> readTChan c myThreadId >>= killThread threadDelay 1000000 atomically (writeTVar r True)
The thread stops on readTChan, but exits when I change the TVar, which happens before the readTChan.
Should I trust this is the correct STM behaviour , and will not change in different implementations ?
This is correct behaviour. Remember, STM transactions execute atomically, so it doesn't make sense to think of a transaction as being blocked at a particular point in the code. A blocked transaction is just waiting for a state in which it can execute all at once. Calling "retry" is saying that this transaction is not yet ready to execute. As noted by Alberto, readTChan calls "retry" to indicate that it (and whatever transaction called it) cannot execute when the channel is empty. Putting it all together, you can see that your transaction will execute when (and only when) "r" contains True, or when "c" is not empty. Hope that helps, Matthew