This function does not create a memory barrier and can be reordered
with other independent reads and writes within a thread, which may cause issues
for multithreaded execution. In these cases, consider using atomicWriteIORef
instead. See Data.IORef#memmodel for more details.
Atomically apply a function to the contents of an IORef,
installing its first component in the IORef and returning
the old contents and the result of applying the function.
The result of the function application (the pair) is not forced.
As a result, this can lead to memory leaks. It is generally better
to use atomicModifyIORef2.
Atomically apply a function to the contents of an IORef,
installing its first component in the IORef and returning
the old contents and the result of applying the function.
The result of the function application (the pair) is forced,
but neither of its components is.
Atomically apply a function to the contents of an
IORef and return the old and new values. The result
of the function is not forced. As this can lead to a
memory leak, it is usually better to use atomicModifyIORef'_.
A strict version of atomicModifyIORef. This forces both the
value stored in the IORef and the value returned.
Conceptually,
atomicModifyIORef' ref f = do
-- Begin atomic block
old <- readIORef ref
let r = f old
new = fst r
writeIORef ref new
-- End atomic block
case r of
(!_new, !res) -> pure res
The actions in the "atomic block" are not subject to interference
by other threads. In particular, the value in the IORef cannot
change between the readIORef and writeIORef invocations.
The new value is installed in the IORef before either value is forced.
So
atomicModifyIORef' ref (x -> (x+1, undefined))
will increment the IORef and then throw an exception in the calling
thread.
atomicModifyIORef' ref (x -> (undefined, x))
and
atomicModifyIORef' ref (_ -> undefined)
will each raise an exception in the calling thread, but will also
install the bottoming value in the IORef, where it may be read by
other threads.
This function imposes a memory barrier, preventing reordering around
the "atomic block"; see Data.IORef#memmodel for details.