
I have proposed[1] the replacement of the atomicModifyMutVar# primop, and the addition of two cheaper but less capable ones. It seems likely that the proposal will succeed, but that the GHC steering committee will leave the question of user interface changes to the libraries list. I would like to open the discussion here. The new primops lead naturally to several thin wrappers: -- Atomically replace the IORef contents -- with the first component of the result of -- applying the function to the old contents. -- Return the old value and the result of -- applying the function, without forcing the latter. -- -- atomicModifyIORef ref f = do -- (_old, ~(_new, res)) <- atomicModifyIORef2Lazy ref f -- return res atomicModifyIORef2Lazy :: IORef a -> (a -> (a, b)) -> IO (a, (a, b)) -- Atomically replace the IORef contents -- with the result of applying the function -- to the old contents. Return the old and -- new contents without forcing the latter. atomicModifyIORefLazy_ :: IORef a -> (a -> a) -> IO (a, a) -- Atomically replace the IORef contents -- with the given value and return the old -- contents. -- -- atomicWriteIORef ref x = void (atomicSwapIORef ref x) atomicSwapIORef :: IORef a -> a -> IO a Based on the code I've read that uses atomicModifyIORef, I believe that the complete laziness of atomicModifyIORef2Lazy and atomicModifyIORefLazy_ is very rarely desirable. I therefore believe we should also (or perhaps instead?) offer stricter versions: atomicModifyIORef2 :: IORef a -> (a -> (a, b)) -> IO (a, (a, b)) atomicModifyIORef2 ref f = do r@(_old, (_new, _res)) <- atomicModifyIORef2Lazy ref f return r atomicModifyIORef_ :: IORef a -> (a -> a) -> IO (a, a) atomicModifyIORef_ ref f = do r@(_old, !_new) <- atomicModifyIORefLazy_ ref f return r The classic atomicModifyIORef also admits a less gratuitously lazy version: atomicModifyIORefNGL :: IORef a -> (a -> (a,b)) -> IO b atomicModifyIORefNGL ref f = do (_old, (_new, res)) <- atomicModifyIORef2 ref f return res Should we add that as well (with a better name)? Should we even consider *replacing* the current atomicModifyIORef with that version? That could theoretically break existing code, but I suspect it would do so very rarely. If we don't change the existing atomicModifyIORef now, I think we should consider deprecating it: it's very easy to accidentally use it too lazily.