STMSoftware Transactional Memory
in Frege - a purely functional JVM language Quickie
OOP 2016
Dierk König Canoo
mittie
Dierk König Canoo
mittie
Silly Clock
10010
Silly Clock
10010 every ms
Silly Clock
10010 every ms
on overflow
Silly Clock
10010 every ms
on overflow
every so often
Transactional Variables
10010
CounterCounter
millissecs
TVar Int
Create new TVartype Counter = TVar Int
newCounter :: STM CounternewCounter = TVar.new 0
STM action type
Read & Write TVartick :: Counter -> STM ()tick counter = do value <- counter.read counter.write (value + 1)
STM action (no IO)
Check transaction invariantmaxTick :: Counter -> Int -> STM ()maxTick counter max = do tick counter value <- counter.read check (value <= max)
Check transaction invariantmaxTick :: Counter -> Int -> STM ()maxTick counter max = do tick counter value <- counter.read check (value <= max)
Composition !
Consistent updateonOverflow :: Counter->Counter->Int->STM ()onOverflow counter overflowCounter max = do value <- counter.read check (value == max) tick overflowCounter reset counter
Composition !
Type of reset enforcedreset :: Counter -> STM ()reset counter = counter.write 0
must be STM action
Atomicallyreport :: Counter -> Counter -> IO ()report millis secs = do (millisValue, secsValue) <- atomically $ do a <- millis.read b <- secs.read return (a, b) println $ show secsValue ++ " " ++ show millisValue
Transaction demarcation calls STM action inside IO action
Starting the threadsmain _ = do millis <- atomically newCounter secs <- atomically newCounter milliOverflow = 1000 runTicker = maxTick millis milliOverflow runSec = onOverflow millis secs milliOverflow
forkOS $ forever (atomically runTicker >> Thread.sleep 1) forkOS $ forever (atomically runSec ) forever (report millis secs >> Thread.sleep 100)
STMWorks like compare and swap but for all TVars inside an atomically functionplus invariants (check)plus alternatives (orElse)plus proper exception handling
No locks -> No deadlocks
First one wins
isolated work commit
failretry
STMReplaces all your locks just like GC replaces manual memory management
Makes compositional and modular code
Is optimistic and thus works best in low contention scenarios
Is not a panacea (sorry).
Classic: Account transferdeposit :: Account -> Int -> STM ()deposit account amount = do balance <- account.read account.write (balance + amount)
withdraw :: Account -> Int -> STM ()withdraw account amount = deposit account (- amount) -- composed
limitedWithdraw :: Account -> Int -> STM ()limitedWithdraw account amount = do withdraw account amount -- composed balance <- account.read check (balance >= 0)
transfer :: Account -> Account -> Int -> STM ()transfer from to amount = do limitedWithdraw from amount -- composed deposit to amount -- composed
Classic: Ant colony
AntsFood Pheromones Evaporation Reporter
STM relies upon
STM relies uponNo access to TVars outside transactionsNo side effects inside transactions
STM relies uponNo access to TVars outside transactionsNo side effects inside transactions
TYPE SYSTEM (pure FP)Developer discipline (everybody else)
STM relies uponNo access to TVars outside transactionsNo side effects inside transactions
TYPE SYSTEM (pure FP)Developer discipline (everybody else)
www.frege-lang.org is the only option on the JVM
Dierk König canoo
mittie
Credits Volker Steiss master thesis Simon Peyton-Jones Beautiful concurrency
Dierk König canoo
mittie
Please give feedback!
Credits Volker Steiss master thesis Simon Peyton-Jones Beautiful concurrency
Top Related