Skip to content

Commit a41308f

Browse files
committed
lock-less position mapping
1 parent 4809f0f commit a41308f

File tree

1 file changed

+19
-20
lines changed

1 file changed

+19
-20
lines changed

ghcide/src/Development/IDE/Core/Shake.hs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ data ShakeExtras = ShakeExtras
198198
,publishedDiagnostics :: STM.Map NormalizedUri [Diagnostic]
199199
-- ^ This represents the set of diagnostics that we have published.
200200
-- Due to debouncing not every change might get published.
201-
,positionMapping :: Var (HMap.HashMap NormalizedUri (Map TextDocumentVersion (PositionDelta, PositionMapping)))
201+
,positionMapping :: STM.Map NormalizedUri (Map TextDocumentVersion (PositionDelta, PositionMapping))
202202
-- ^ Map from a text document version to a PositionMapping that describes how to map
203203
-- positions in a version of that document to positions in the latest version
204204
-- First mapping is delta from previous version and second one is an
@@ -323,7 +323,6 @@ getIdeOptionsIO ide = do
323323
-- for the version of that value.
324324
lastValueIO :: IdeRule k v => ShakeExtras -> k -> NormalizedFilePath -> IO (Maybe (v, PositionMapping))
325325
lastValueIO s@ShakeExtras{positionMapping,persistentKeys,state} k file = do
326-
allMappings <- readVar positionMapping
327326

328327
let readPersistent
329328
| IdeTesting testing <- ideTesting s -- Don't read stale persistent values in tests
@@ -341,7 +340,7 @@ lastValueIO s@ShakeExtras{positionMapping,persistentKeys,state} k file = do
341340
return Nothing
342341
Just (v,del,ver) -> do
343342
void $ atomically $ STM.focus (Focus.alter (alterValue $ Stale (Just del) ver (toDyn v))) (toKey k file) state
344-
return $ Just (v,addDelta del $ mappingForVersion allMappings file ver)
343+
atomically $ Just . (v,) . addDelta del <$> mappingForVersion positionMapping file ver
345344

346345
-- We got a new stale value from the persistent rule, insert it in the map without affecting diagnostics
347346
alterValue new Nothing = Just (ValueWithDiagnostics new mempty) -- If it wasn't in the map, give it empty diagnostics
@@ -354,8 +353,10 @@ lastValueIO s@ShakeExtras{positionMapping,persistentKeys,state} k file = do
354353
atomically (STM.lookup (toKey k file) state) >>= \case
355354
Nothing -> readPersistent
356355
Just (ValueWithDiagnostics v _) -> case v of
357-
Succeeded ver (fromDynamic -> Just v) -> pure (Just (v, mappingForVersion allMappings file ver))
358-
Stale del ver (fromDynamic -> Just v) -> pure (Just (v, maybe id addDelta del $ mappingForVersion allMappings file ver))
356+
Succeeded ver (fromDynamic -> Just v) ->
357+
atomically $ Just . (v,) <$> mappingForVersion positionMapping file ver
358+
Stale del ver (fromDynamic -> Just v) ->
359+
atomically $ Just . (v,) . maybe id addDelta del <$> mappingForVersion positionMapping file ver
359360
Failed p | not p -> readPersistent
360361
_ -> pure Nothing
361362

@@ -367,14 +368,13 @@ lastValue key file = do
367368
liftIO $ lastValueIO s key file
368369

369370
mappingForVersion
370-
:: HMap.HashMap NormalizedUri (Map TextDocumentVersion (a, PositionMapping))
371+
:: STM.Map NormalizedUri (Map TextDocumentVersion (a, PositionMapping))
371372
-> NormalizedFilePath
372373
-> TextDocumentVersion
373-
-> PositionMapping
374-
mappingForVersion allMappings file ver =
375-
maybe zeroMapping snd $
376-
Map.lookup ver =<<
377-
HMap.lookup (filePathToUri' file) allMappings
374+
-> STM PositionMapping
375+
mappingForVersion allMappings file ver = do
376+
mapping <- STM.lookup (filePathToUri' file) allMappings
377+
return $ maybe zeroMapping snd $ Map.lookup ver =<< mapping
378378

379379
type IdeRule k v =
380380
( Shake.RuleResult k ~ v
@@ -506,7 +506,7 @@ shakeOpen lspEnv defaultConfig logger debouncer
506506
diagnostics <- STM.newIO
507507
hiddenDiagnostics <- STM.newIO
508508
publishedDiagnostics <- STM.newIO
509-
positionMapping <- newVar HMap.empty
509+
positionMapping <- STM.newIO
510510
knownTargetsVar <- newVar $ hashed HMap.empty
511511
let restartShakeSession = shakeRestart ideState
512512
persistentKeys <- newVar HMap.empty
@@ -1216,17 +1216,16 @@ getAllDiagnostics =
12161216
fmap (concatMap (\(k,v) -> map (fromUri k,ShowDiag,) $ getDiagnosticsFromStore v)) . ListT.toList . STM.listT
12171217

12181218
updatePositionMapping :: IdeState -> VersionedTextDocumentIdentifier -> List TextDocumentContentChangeEvent -> IO ()
1219-
updatePositionMapping IdeState{shakeExtras = ShakeExtras{positionMapping}} VersionedTextDocumentIdentifier{..} (List changes) = do
1220-
modifyVar_ positionMapping $ \allMappings -> do
1221-
let uri = toNormalizedUri _uri
1222-
let mappingForUri = HMap.lookupDefault Map.empty uri allMappings
1223-
let (_, updatedMapping) =
1219+
updatePositionMapping IdeState{shakeExtras = ShakeExtras{positionMapping}} VersionedTextDocumentIdentifier{..} (List changes) =
1220+
atomically $ STM.focus (Focus.alter f) uri positionMapping
1221+
where
1222+
uri = toNormalizedUri _uri
1223+
f = Just . f' . fromMaybe mempty
1224+
f' mappingForUri = snd $
12241225
-- Very important to use mapAccum here so that the tails of
12251226
-- each mapping can be shared, otherwise quadratic space is
12261227
-- used which is evident in long running sessions.
12271228
Map.mapAccumRWithKey (\acc _k (delta, _) -> let new = addDelta delta acc in (new, (delta, acc)))
12281229
zeroMapping
12291230
(Map.insert _version (shared_change, zeroMapping) mappingForUri)
1230-
pure $ HMap.insert uri updatedMapping allMappings
1231-
where
1232-
shared_change = mkDelta changes
1231+
shared_change = mkDelta changes

0 commit comments

Comments
 (0)