I got stuck in understanding the concept of atomically in STM.
I illustrate with an example
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import qualified Data.Map as Map
main :: IO ()
main = do
d <- atomically$ newTVar Map.empty
sockHandler d
sockHandler :: TVar (Map.Map String Int)-> IO ()
sockHandler d = do
forkIO $ commandProcessor d 1
forkIO $ commandProcessor d 2
forkIO $ commandProcessor d 3
forkIO $ commandProcessor d 4
forkIO (threadDelay 1000 >> putStrLn "Hello World?")
threadDelay 10000
return ()
commandProcessor :: TVar (Map.Map String Int)-> Int-> IO ()
commandProcessor d i= do
addCommand d i
commandProcessor d i
addCommand :: TVar (Map.Map String Int) ->Int -> IO ()
addCommand d i = do
succ <- atomically $ runAdd d
putStrLn $"Result of add in " ++ (show i)++ " " ++( show succ)
runAdd d =do
dl <- readTVar d
let (succ,g)= if Map.member "a" dl
then
(False,dl)
else
(True,Map.insert "a" 9 dl)
writeTVar d g
return succ
The sample output would be like this:
Result of add in 1 True Result of add in 4 False Result of add in 1 FalseResult of add in 2 FalseResult of add in 3 False Hello World? Result of add in 4 False
Result of add in 1 FalseResult of add in 2 False Result of add in 3 False Result of add in 4 False
Result of add in 1 False Result of add in 2 FalseResult of add in 3 FalseResult of add in 4 False
Result of add in 1 False Result of add in 2 FalseResult of add in 3 FalseResult of add in 4 False
Result of add in 1 False Result of add in 2 FalseResult of add in 4 FalseResult of add in 3 False
Result of add in 1 False Result of add in 4 FalseResult of add in 2 FalseResult of add in 3 False
Result of add in 1 FalseResult of add in 4 False Result of add in 2 False Result of add in 3 False
Result of add in 1 FalseResult of add in 4 False
Result of add in 2 FalseResult of add in 3 False
Result of add in 1 FalseResult of add in 4 False
Result of add in 2 FalseResult of add in 3 False Result of add in 1 False Result of add in 4 False
Result of add in 2 FalseResult of add in 3 False
Result of add in 1 FalseResult of add in 4 False
When I read about atomically
. This means that all operations inside the transaction fully complete, without any other threads modifying the variables that our transaction is using, or it fails, and the state is rolled back to where it was before the transaction was begun. In short, atomic transactions either complete fully, or it is as if they were never run at all.
So to the question could the "return" of succ in some cases never happen? That is could the line succ <- atomically $ runAdd d putStrLn $"Result of add in " ++ (show i)++ " " ++( show succ)
give an output of "Result of add in ?i " ("as if they were never run at all")
If a transaction does get rolled back, what happens is that your program tries again. You can imagine the implementation of atomically
to be something like this:
atomically action = do varState <- getStateOfTVars
(newState, ret) <- runTransactionWith action varState
success <- attemptToCommitChangesToTVars newState
if success
then return ret
else atomically action -- try again
In your case, the transaction will always run and will always complete. It may complete on the second or third try due to conflicts, but that's invisible to you, the user. STM makes sure that the action happens atomically, even if it takes a few goes before it's able to do that successfully.