
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