Question

Disclaimer: This can easily be done using an MVar () as a simple mutex. I'm just curios to see whether it can be done with STM.

I want to do the following atomically:

  • Read some variables.

  • Decide what I/O to perform, based on what I just read.

  • Perform the I/O.

  • Record the results in the variables.

For concreteness, suppose I want to keep track of how many bytes of input I've read, and pretend I've reached EOF after a certain number of bytes have been consumed. (OK, letting two threads read from the same file concurrently is probably a bogus thing to do in the first place, but go with me on this...)

Clearly this cannot be a single STM transaction; there's I/O in the middle. Clearly it would also be wrong to have it as two unconnected transactions. (Two threads could see that there's one byte of quota left, and both decide to read that byte.)

Is there a nice solution to this problem? Or is STM simply the wrong tool for this task?

Was it helpful?

Solution 3

I'd say STM can't do it, and it's on purpose. A piece of STM code can be restarted multiple times at various places if a transaction rolls back. What would happen if you run your transaction, it performs the I/O action and then rolls back when recording the results in the variables?

For this reason STM computations must be pure, only with the addition of STM primitives such as STM mutable variables and arrays.

OTHER TIPS

Use a TVar Bool named consistent to keep track of whether your IO action is in progress. Before you run the IO action you set consistent to False and after you run the IO action you set consistent to True. Then, any action that depends on the values of those STM variables that you are modifying just puts this clause at the beginning:

do b <- readTVar consistent
   check b
   ...

This ensures that those actions only see a consistent view of the variables being modified and will not run while the IO action is in progress.

I think you are looking for the stm-io-hooks package.

Whatever you actually want to do – would it be possible to express that in terms of STM's abort/retry semantics? In other words: Can you do a rollback and repeat the IO action? If not, then I'd refer to the answer of Gabriel Gonzalez.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top