[Haskell-cafe] STM atomic blocks in IO functions
wren ng thornton
wren at freegeek.org
Sat Jan 14 23:12:02 CET 2012
On 1/14/12 2:24 PM, Rob Stewart wrote:
> Are IO functions permissible in STM atomically blocks?
They are not. The semantics of STM are that each transaction is retried
until it succeeds, and that the number of times it is retried does not
affect the program output. Thus, you can only do things in STM which can
be reverted, since you may have to undo the side-effects whenever the
transaction is retried.
However, if you're interested in pursuing this approach, you should take
a look at TwilightSTM which expands the interaction possibilities
between IO and STM.
> If so how? If
> not, how would one get around a problem of having to use an IO
> function to retrieve a value that is to be written to a TVar ?
If you truly must do IO in the middle of a transaction, the typical
solution is to use a locking mechanism. For example, you use a TMVar()
as the lock: taking the () token in order to prevent other threads from
doing the IO; doing the IO; and then putting the () token back. Thus,
something like:
do ...
atomically $ do
...
() <- takeTMVar lockRunFoo
x <- runFoo
atomically $ do
putTMVar lockRunFoo ()
...x...
...
However, it's often possible to factor the IO out of the original
transaction, so you should do so whenever you can. An unfortunate
downside of the above locking hack is that the STM state is not
guaranteed to be consistent across the two transactions. You can fake
read-consistency by moving reads into the first transaction in order to
bind the values to local variables, as in:
do ...
(a,b,c) <- atomically $ do
...
a <- ...
...
b <- ...
...
c <- ...
...
() <- takeTMVar lockRunFoo
return (a,b,c)
x <- runFoo
atomically $ do
putTMVar lockRunFoo ()
...x...a...b...c...
...
And you can fake write-consistency by moving writes into the second
transaction to ensure that they all are committed at once. However, you
can't use those tricks if you have a complicated back and forth with
reading and writing.
--
Live well,
~wren
More information about the Haskell-Cafe
mailing list