I am experimenting with STM by implementing the dining philsophers problems.
Anyway, I have the following definitions.
data ChopStick = CS (TVar Bool)
takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
isTaken <- readTVar chopstick
check (isTaken)
writeTVar chopstick True
This function is called atomically:
atomically $ do
takeChopstick leftChopstick
takeChopstick rightChopstick
When running the program with the above definition of takeChopstick, I experience different results to running it with this definition:
takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
isTaken <- readTVar chopstick
if isTaken
then retry
else writeTVar chopstick True
In particular, the program hangs.
The source code for check (hackage, stm-2.2.0.1) is as follows:
check :: Bool -> STM a
check b = if b then return undefined else retry
Which appears to be effectively the same as my explicit use of retry.
How does check differ to explicitly using retry? Is pushing the retry call further down causing it to restart a different atomic block?
No,
checkis no different than to usingretryexplicitly, I simply confused the argument tocheck.The solution is to
checkthatisTakenisFalse, i.e.,check $ not isTaken.