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,
check
is no different than to usingretry
explicitly, I simply confused the argument tocheck
.The solution is to
check
thatisTaken
isFalse
, i.e.,check $ not isTaken
.