Skip to content

Commit 67a14f5

Browse files
committed
lock-less diagnostics
1 parent 48f0b11 commit 67a14f5

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

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

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ data ShakeExtras = ShakeExtras
191191
,logger :: Logger
192192
,globals :: Var (HMap.HashMap TypeRep Dynamic)
193193
,state :: Values
194-
,diagnostics :: Var DiagnosticStore
195-
,hiddenDiagnostics :: Var DiagnosticStore
194+
,diagnostics :: STMDiagnosticStore
195+
,hiddenDiagnostics :: STMDiagnosticStore
196196
,publishedDiagnostics :: STM.Map NormalizedUri [Diagnostic]
197197
-- ^ This represents the set of diagnostics that we have published.
198198
-- Due to debouncing not every change might get published.
@@ -509,8 +509,8 @@ shakeOpen lspEnv defaultConfig logger debouncer
509509
shakeExtras <- do
510510
globals <- newVar HMap.empty
511511
state <- STM.newIO
512-
diagnostics <- newVar mempty
513-
hiddenDiagnostics <- newVar mempty
512+
diagnostics <- STM.newIO
513+
hiddenDiagnostics <- STM.newIO
514514
publishedDiagnostics <- STM.newIO
515515
positionMapping <- newVar HMap.empty
516516
knownTargetsVar <- newVar $ hashed HMap.empty
@@ -758,13 +758,11 @@ instantiateDelayedAction (DelayedAction _ s p a) = do
758758

759759
getDiagnostics :: IdeState -> IO [FileDiagnostic]
760760
getDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} = do
761-
val <- readVar diagnostics
762-
return $ getAllDiagnostics val
761+
atomically $ getAllDiagnostics diagnostics
763762

764763
getHiddenDiagnostics :: IdeState -> IO [FileDiagnostic]
765764
getHiddenDiagnostics IdeState{shakeExtras = ShakeExtras{hiddenDiagnostics}} = do
766-
val <- readVar hiddenDiagnostics
767-
return $ getAllDiagnostics val
765+
atomically $ getAllDiagnostics hiddenDiagnostics
768766

769767
-- | Find and release old keys from the state Hashmap
770768
-- For the record, there are other state sources that this process does not release:
@@ -1154,17 +1152,14 @@ updateFileDiagnostics fp k ShakeExtras{logger, diagnostics, hiddenDiagnostics, p
11541152
let (currentShown, currentHidden) = partition ((== ShowDiag) . fst) current
11551153
uri = filePathToUri' fp
11561154
ver = vfsVersion =<< modTime
1157-
update new store =
1158-
let store' = setStageDiagnostics uri ver (T.pack $ show k) new store
1159-
new' = getUriDiagnostics uri store'
1160-
in (store', new')
1155+
update new store = setStageDiagnostics uri ver (T.pack $ show k) new store
11611156
mask_ $ do
11621157
-- Mask async exceptions to ensure that updated diagnostics are always
11631158
-- published. Otherwise, we might never publish certain diagnostics if
11641159
-- an exception strikes between modifyVar but before
11651160
-- publishDiagnosticsNotification.
1166-
newDiags <- modifyVar diagnostics $ pure . update (map snd currentShown)
1167-
_ <- modifyVar hiddenDiagnostics $ pure . update (map snd currentHidden)
1161+
newDiags <- liftIO $ atomically $ update (map snd currentShown) diagnostics
1162+
_ <- liftIO $ atomically $ update (map snd currentHidden) hiddenDiagnostics
11681163
let uri = filePathToUri' fp
11691164
let delay = if null newDiags then 0.1 else 0
11701165
registerEvent debouncer delay uri $ do
@@ -1191,10 +1186,21 @@ actionLogger = do
11911186
ShakeExtras{logger} <- getShakeExtras
11921187
return logger
11931188

1189+
--------------------------------------------------------------------------------
1190+
type STMDiagnosticStore = STM.Map NormalizedUri StoreItem
11941191

11951192
getDiagnosticsFromStore :: StoreItem -> [Diagnostic]
11961193
getDiagnosticsFromStore (StoreItem _ diags) = concatMap SL.fromSortedList $ Map.elems diags
11971194

1195+
updateSTMDiagnostics :: STMDiagnosticStore
1196+
-> NormalizedUri -> TextDocumentVersion -> DiagnosticsBySource
1197+
-> STM [LSP.Diagnostic]
1198+
updateSTMDiagnostics store uri mv newDiagsBySource =
1199+
getDiagnosticsFromStore . fromJust <$> STM.focus (Focus.alter update *> Focus.lookup) uri store
1200+
where
1201+
update (Just(StoreItem mvs dbs))
1202+
| mvs == mv = Just (StoreItem mv (newDiagsBySource <> dbs))
1203+
update _ = Just (StoreItem mv newDiagsBySource)
11981204

11991205
-- | Sets the diagnostics for a file and compilation step
12001206
-- if you want to clear the diagnostics call this with an empty list
@@ -1203,25 +1209,17 @@ setStageDiagnostics
12031209
-> TextDocumentVersion -- ^ the time that the file these diagnostics originate from was last edited
12041210
-> T.Text
12051211
-> [LSP.Diagnostic]
1206-
-> DiagnosticStore
1207-
-> DiagnosticStore
1208-
setStageDiagnostics uri ver stage diags ds = updateDiagnostics ds uri ver updatedDiags
1212+
-> STMDiagnosticStore
1213+
-> STM [LSP.Diagnostic]
1214+
setStageDiagnostics uri ver stage diags ds = updateSTMDiagnostics ds uri ver updatedDiags
12091215
where
12101216
updatedDiags = Map.singleton (Just stage) (SL.toSortedList diags)
12111217

12121218
getAllDiagnostics ::
1213-
DiagnosticStore ->
1214-
[FileDiagnostic]
1219+
STMDiagnosticStore ->
1220+
STM [FileDiagnostic]
12151221
getAllDiagnostics =
1216-
concatMap (\(k,v) -> map (fromUri k,ShowDiag,) $ getDiagnosticsFromStore v) . HMap.toList
1217-
1218-
getUriDiagnostics ::
1219-
NormalizedUri ->
1220-
DiagnosticStore ->
1221-
[LSP.Diagnostic]
1222-
getUriDiagnostics uri ds =
1223-
maybe [] getDiagnosticsFromStore $
1224-
HMap.lookup uri ds
1222+
fmap (concatMap (\(k,v) -> map (fromUri k,ShowDiag,) $ getDiagnosticsFromStore v)) . ListT.toList . STM.listT
12251223

12261224
updatePositionMapping :: IdeState -> VersionedTextDocumentIdentifier -> List TextDocumentContentChangeEvent -> IO ()
12271225
updatePositionMapping IdeState{shakeExtras = ShakeExtras{positionMapping}} VersionedTextDocumentIdentifier{..} (List changes) = do

0 commit comments

Comments
 (0)