basvandijk/mighttpd2 — comment on commit aea2b5a10cf89d8858378b7198d96b8a8d09ef31
File:  line 0
By basvandijk:

The risk that you are probably talking about is an inconsistent view of the value of the IORef when you're about to write it.

For example if you have to threads that modify a bank account:

thread1 = do balance <- readIORef bankAccount
writeIORef bankAccount (balance + 10)

thread2 = do balance <- readIORef bankAccount
writeIORef bankAccount (balance - 100)

if `thread2` gets executed between the `readIORef` and `writeIORef` of `thread1` the final value of the IORef will be `balance + 10` which is probabaly not what you intended.

We can solve it by using `atomicModifyIORef`

thread1 = do balance' <- atomicModifyIORef bankAccount (\balance -> let balance' = balance + 10 in (balance', balance')
balance' `seq` return () -- to prevent stack overflows

thread2 = do balance' <- atomicModifyIORef bankAccount (\balance -> let balance' = balance - 100 in (balance', balance')
balance' `seq` return () -- to prevent stack overflows

`atomicModifyIORef` guarantees that the value that is read (`balance`) will be consistent until you write it (I believe `atomicModifyIORef` internally works with a compare-and-swap (CAS) instruction)

However in your case you don't use the previous value so there's never any risk of inconsistency.

It's maybe wise to discuss this more publicly on [the thread on the haskell-cafe mailinglist that I started](http://www.haskell.org/pipermail/haskell-cafe/2011-October/096377.html) to see if I missed something.