Skip to content

Expand compatibility note for readMVar

Currently, the note reads

Compatibility note: Prior to base 4.7, readMVar was a combination of takeMVar and putMVar. This mean that in the presence of other threads attempting to putMVar, readMVar could block. Furthermore, readMVar would not receive the next putMVar if there was already a pending thread blocked on takeMVar. The old behavior can be recovered by [...]

I don't think this goes quite far enough. Consider the following scenario:

main = do
  mv <- newEmptyMVar
  forkIO $ putMVar mv "a" >> ... >> takeMVar mv >>= ...
  forkIO $ putMVar mv "b" >> ... >> takeMVar mv >>= ...
  ...
  readMVar mv

(assume none of the ...s touch mv)

With the current implementation of readMVar, each child thread will put its value in the MVar and then take that same value out. They may do so in either order, and the order will determine what value the main thread reads.

With the old implementation of readMVar, there are two additional (symmetrical) possibilities. In one, the first child puts "a", the main thread takes "a", the second child puts "b", the first child takes "b", the main thread puts "a", and the second child takes "a".

So the old version of readMVar could make an interaction between other threads substantially less deterministic. I believe the note should probably reflect that. Its language also could really use some clarification in general.

Trac metadata
Trac field Value
Version 8.2.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Core Libraries
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information