Silly question about IORefs and MVars

Alastair Reid
23 Nov 2002 13:48:03 +0000

Nicolas Oury <> writes:
> I wonder why IORefs updates aren't safe : it seems that preemptive
> scheduling takes place during memory allocation and I can't see
> where there could be an allocation (and so a switch) in a read or a
> write of an IORef.

Here's a typical code sequence:

  foo rx = do
    x <- readIORef rx
    writeIORef rx (x+1)

but GHC will 'desugar' this code to:

  foo rx = do
    x <- readIORef rx
    let x' = (+) x 1          -- build a thunk
    writeIORef rx x'

Building thunks allocates memory which can cause context switches so
foo does not execute atomically.

Simpler code which merely swaps the current value for a new value
would seem to be immune to such problems but then you have to figure
that 'do' expressions are merely syntactic sugar for a bunch of calls
to >>= and >>.  These might allocate memory.

And, finally, it's possible that writeIORef is, somehow, a thunk.  For
example, writeIORef used to have a different name like writeRef or
writeIOVar or some such.  The easiest way to rename this variable
would be to write:

  writeIORef = writeRef

So, when you call writeIORef you might cause evaluation of a thunk.
Evaluating thunks can allocate memory.

Alastair Reid

ps It's best to avoid relying on compilers not to context switch at
particular times unless it is documented that this is a property you
can rely on.  That kind of reasoning tends to break down when your
compiler gets smarter or you switch compilers or...