summaryrefslogtreecommitdiff
path: root/compiler/iface/IfaceEnv.lhs
diff options
context:
space:
mode:
authorThomas Schilling <nominolo@googlemail.com>2009-08-18 21:32:43 +0000
committerThomas Schilling <nominolo@googlemail.com>2009-08-18 21:32:43 +0000
commitcadba81047f6188fad2fe07004c3cb36316c36d1 (patch)
treebc976b2fd4d00a7df8b2e7614afb162fdf54a94e /compiler/iface/IfaceEnv.lhs
parentc5cafbcca54c4b1117bc43b31d86afa583fb7f62 (diff)
downloadhaskell-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.lhs40
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}