This is the code of modifyMVar_
. The comment says it allows multiple writers. And that it replaces the original content if an exception happens. I am not 100% sure about my understanding where it happens looking at the code.
putMVar
is not atomic (obviously it is not) and another thread puts its own content faster. Is it the place?restore
returns taken a
value back. Do they mean again possibility of multiple writers during putMVar
but now in the "exception handler"?modifyMVar
as a synchronized code block? Like a mutex in Java or in Python? It seems yes, but what could be a problem in comparison with a standard lock/mutex in other languages? I think the io
argument is executed mutually exclusive as in a standard lock, is not it?{-|
An exception-safe wrapper for modifying the contents of an 'MVar'.
Like 'withMVar', 'modifyMVar' will replace the original contents of
the 'MVar' if an exception is raised during the operation. This
function is only atomic if there are no other producers for this
'MVar'. In other words, it cannot guarantee that, by the time
'modifyMVar_' gets the chance to write to the MVar, the value
of the MVar has not been altered by a write operation from another thread.
-}
{-# INLINE modifyMVar_ #-}
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()
modifyMVar_ m io =
mask $ \restore -> do
a <- takeMVar m
a' <- restore (io a) `onException` putMVar m a
putMVar m a'
- where does it allow another writer to alter the content?
I assume you are referring to this part of the documentation:
This function is only atomic if there are no other producers for this
MVar
.
The idea behind modifyMVar_
is that if there are multiple concurrent modifyMVar_
, one of them will run its takeMVar
, and now the MVar
is empty so all the other modifyMVar_
will block on takeMVar
. This guarantees that modifyMVar_
(on the same variable) will run sequentially, and therefore atomically.
If another thread uses putMVar
directly (instead of indirectly via modifyMVar_
), that will unlock a waiting modifyMVar_
, which breaks the atomicity guarantee.
- where does it replace the original content on exception?
action `onException` putMVar m a
runs action
and if it raises an exceptions, runs putMVar m a
before re-raising the exception.
- Can I use modifyMVar as a synchronized code block?
Yes, an MVar ()
is a mutex.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With