diff options
author | David Feuer <David.Feuer@gmail.com> | 2017-05-03 09:47:32 -0400 |
---|---|---|
committer | David Feuer <David.Feuer@gmail.com> | 2017-05-03 09:47:32 -0400 |
commit | aed2d85f5deacc0e9b0500eb5b1095643e536581 (patch) | |
tree | 23ba234c2d01eefa3d9eea7e93198d460ad0e319 | |
parent | fdd659bf85617983c2a3da16a5ceb28a16f65cf9 (diff) | |
download | haskell-wip/dfeuer-interleave-mvars.tar.gz |
Switch to single-MVar unsafeInterleaveIOwip/dfeuer-interleave-mvars
Ben Gamari has pointed out that using two `MVar`s may be reducing
efficiency. Let's see what happens with an `MVar . Maybe` approach.
The next potential stage is to switch from `Maybe` to null pointers.
-rw-r--r-- | libraries/base/GHC/IO/Unsafe.hs | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/libraries/base/GHC/IO/Unsafe.hs b/libraries/base/GHC/IO/Unsafe.hs index 5498e19c95..3c958c1b84 100644 --- a/libraries/base/GHC/IO/Unsafe.hs +++ b/libraries/base/GHC/IO/Unsafe.hs @@ -112,18 +112,29 @@ file reading, see 'System.IO.hGetContents'. {-# INLINE unsafeInterleaveIO #-} unsafeInterleaveIO :: IO a -> IO a unsafeInterleaveIO m = do - claimedV <- newEmptyMVar - resultV <- newEmptyMVar + v <- newMVar Nothing unsafeDupableInterleaveIO $ do - claimSucceeded <- tryPutMVar claimedV () - if claimSucceeded - then do - -- We were the first ones to claim the computation, so we - -- perform it and store the result. - res <- m - putMVar resultV res - pure res - else readMVar resultV + r <- tryTakeMVar v + case r of + -- Someone else has taken the MVar. By the time they put + -- it back, the action will surely have been performed, + -- so we use the result. + Nothing -> do + res <- readMVar v + case res of + Nothing -> errorWithoutStackTrace "unsafeInterleaveIO: impossible Nothing" + Just a -> pure a + + -- Someone else has performed the action, so we use + -- their result and put it back in the MVar. + Just j@(Just r) -> r <$ putMVar v j + + -- We're the first ones to get the MVar, so we actually + -- do the work. + Just Nothing -> do + res <- m + putMVar v (Just res) + pure res -- Note [unsafeDupableInterleaveIO should not be inlined] |