
Jean-Marie Gaillourdet:
the Eq instance of TypeRep shows the same non-deterministic behavior:
Of course, equality on TypeReps is implemented by comparison of the Keys. On Sunday 09 October 2011, 16:40:13, Jean-Marie Gaillourdet wrote:
Hi Daniel,
I've been chasing the source of the non-deterministic of my library for quite some time now. And at several points in time I had the impression that modifyMVar would not always be atomic.
It isn't: "MVars offer more flexibility than IORefs, but less flexibility than STM. They are appropriate for building synchronization primitives and performing simple interthread communication; however they are very simple and susceptible to race conditions, deadlocks or uncaught exceptions. Do not use them if you need perform larger atomic operations such as reading from multiple variables: use STM instead. In particular, the bigger functions in this module (readMVar, swapMVar, withMVar, modifyMVar_ and modifyMVar) are simply the composition of a takeMVar followed by a putMVar with exception safety. These only have atomicity guarantees if all other threads perform a takeMVar before a putMVar as well; otherwise, they may block." But I don't think that's the problem here.
(Of course under the assumption that no other code touches the MVar). But in that case as well as in the case here it is only reproducible by looping the execution of the binary. Moving the loop into the Haskell program will show the bug in the first iteration or never.
That's what I expect. I think what happens is: -- from Data.Typeable cache = unsafePerformIO $ ... mkTyConKey :: String -> Key mkTyConKey str = unsafePerformIO $ do let Cache {next_key = kloc, tc_tbl = tbl} = cache mb_k <- HT.lookup tbl str case mb_k of Just k -> return k Nothing -> do { k <- newKey kloc ; HT.insert tbl str k ; return k } occasionally, the second thread gets to perform the lookup before the first has updated the cache, so both threads create a new entry and update the cache. If you loop in the Haskell programme, after the first round each thread definitely finds an entry for "()", so the cache isn't updated anymore.
I will report a bug.
Jean