diff options
author | Thomas Schilling <nominolo@googlemail.com> | 2009-08-18 21:32:43 +0000 |
---|---|---|
committer | Thomas Schilling <nominolo@googlemail.com> | 2009-08-18 21:32:43 +0000 |
commit | cadba81047f6188fad2fe07004c3cb36316c36d1 (patch) | |
tree | bc976b2fd4d00a7df8b2e7614afb162fdf54a94e /compiler/iface/IfaceEnv.lhs | |
parent | c5cafbcca54c4b1117bc43b31d86afa583fb7f62 (diff) | |
download | haskell-cadba81047f6188fad2fe07004c3cb36316c36d1.tar.gz |
Remove the lock around NameCache for readBinIface.
Turns out using atomic update instead of a full-blown lock was easier
than I thought. It should also be safe in the case where we
concurrently read the same interface file. Whichever thread loses the
race will simply find that all of the names are already defined and
will have no effect on the name cache.
Diffstat (limited to 'compiler/iface/IfaceEnv.lhs')
-rw-r--r-- | compiler/iface/IfaceEnv.lhs | 40 |
1 files changed, 14 insertions, 26 deletions
diff --git a/compiler/iface/IfaceEnv.lhs b/compiler/iface/IfaceEnv.lhs index 313424fadf..34a457e192 100644 --- a/compiler/iface/IfaceEnv.lhs +++ b/compiler/iface/IfaceEnv.lhs @@ -14,7 +14,7 @@ module IfaceEnv ( -- Name-cache stuff allocateGlobalBinder, initNameCache, - getNameCache, lockedUpdNameCache, + getNameCache, mkNameCacheUpdater, NameCacheUpdater ) where #include "HsVersions.h" @@ -37,9 +37,9 @@ import SrcLoc import MkId import Outputable -import Exception ( onException ) +import Exception ( evaluate ) -import Control.Concurrent.MVar ( tryTakeMVar, takeMVar, putMVar ) +import Data.IORef ( atomicModifyIORef, readIORef ) \end{code} @@ -233,31 +233,19 @@ updNameCache upd_fn = do HscEnv { hsc_NC = nc_var } <- getTopEnv atomicUpdMutVar' nc_var upd_fn --- | Update the name cache, but takes a lock while the update function is --- running. If the update function throws an exception the lock is released --- and the exception propagated. -lockedUpdNameCache :: (NameCache -> IO (NameCache, c)) -> TcRnIf a b c -lockedUpdNameCache upd_fn = do - lock <- hsc_NC_lock `fmap` getTopEnv - -- Non-blocking "takeMVar" so we can show diagnostics if we didn't get the - -- lock. - mb_ok <- liftIO $ tryTakeMVar lock - case mb_ok of - Nothing -> do - traceIf (text "lockedUpdNameCache: failed to take lock. blocking..") - _ <- liftIO $ takeMVar lock - traceIf (text "lockedUpdNameCache: got lock") - Just _ -> return () - - name_cache <- getNameCache - (name_cache', rslt) <- liftIO (upd_fn name_cache - `onException` putMVar lock ()) +-- | A function that atomically updates the name cache given a modifier +-- function. The second result of the modifier function will be the result +-- of the IO action. +type NameCacheUpdater c = (NameCache -> (NameCache, c)) -> IO c +-- | Return a function to atomically update the name cache. +mkNameCacheUpdater :: TcRnIf a b (NameCacheUpdater c) +mkNameCacheUpdater = do nc_var <- hsc_NC `fmap` getTopEnv - writeMutVar nc_var $! name_cache' - - liftIO (putMVar lock ()) - return rslt + let update_nc f = do r <- atomicModifyIORef nc_var f + _ <- evaluate =<< readIORef nc_var + return r + return update_nc \end{code} |