Haskell STM Transactions
An STM transaction is a group of reads and writes that succeeds as one step. It runs inside atomically and touches only TVars.
One transaction reads two boxes and adds them
Start with 20 and 22. Read both inside one transaction and add them.
import Control.Concurrent.STM
main :: IO ()
main = do
a <- newTVarIO (20 :: Int)
b <- newTVarIO (22 :: Int)
total <- atomically $ do
x <- readTVar a
y <- readTVar b
return (x + y)
print totalOne transaction changes a value only when it can afford it
Start with 100. Take 30 inside one transaction only when the balance is at least 30.
import Control.Concurrent.STM
import Control.Monad (when)
main :: IO ()
main = do
t <- newTVarIO (100 :: Int)
atomically $ do
v <- readTVar t
when (v >= 30) (writeTVar t (v - 30))
result <- readTVarIO t
print resultOne transaction moves a value between boxes
Start with 30 in the first box and 0 in the second. Move the whole value across in one transaction.
import Control.Concurrent.STM
main :: IO ()
main = do
a <- newTVarIO (30 :: Int)
b <- newTVarIO (0 :: Int)
atomically $ do
v <- readTVar a
writeTVar b v
writeTVar a 0
x <- readTVarIO a
y <- readTVarIO b
print (x, y)Example
import Control.Concurrent.STM
main :: IO ()
main = do
stock <- newTVarIO (50 :: Int)
sold <- newTVarIO (0 :: Int)
atomically $ do
s <- readTVar stock
writeTVar stock (s - 8)
modifyTVar' sold (+ 8)
x <- readTVarIO stock
y <- readTVarIO sold
print (x, y)Key points
- Transaction: a group of reads and writes that succeeds as one step.
- Atomically: atomically runs a transaction and returns its result.
- ReadTVar: readTVar reads a TVar inside a transaction.
- WriteTVar: writeTVar sets a TVar inside a transaction.
- ModifyTVar': modifyTVar' changes a TVar inside a transaction by applying a function.
In this example, stock starts at 50 and sold starts at 0. One transaction takes 8 from stock and adds 8 to sold. The main thread reads both back and prints 42 and 8.
Note
a transaction cannot do ordinary input and output. It touches TVars only.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
What can an STM transaction touch?