Is Haskell's STM `check` different from explicitly using `retry`?

206 views Asked by At

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?

1

There are 1 answers

0
Code Monkey On

No, check is no different than to using retry explicitly, I simply confused the argument to check.

The solution is to check that isTaken is False, i.e., check $ not isTaken.

takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
    isTaken <- readTVar chopstick
    check (not isTaken)
    writeTVar chopstick True