[Haskell-cafe] STM semantics

Matthew Brecknell matthew at brecknell.net
Sat Oct 24 08:51:57 EDT 2009

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

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,

More information about the Haskell-Cafe mailing list