Skip to content

Commit 5f7d870

Browse files
committed
lock-less diagnostics
1 parent 12088e6 commit 5f7d870

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
@@ -193,8 +193,8 @@ data ShakeExtras = ShakeExtras
193193
,logger :: Logger
194194
,globals :: Var (HMap.HashMap TypeRep Dynamic)
195195
,state :: Values
196-
,diagnostics :: Var DiagnosticStore
197-
,hiddenDiagnostics :: Var DiagnosticStore
196+
,diagnostics :: STMDiagnosticStore
197+
,hiddenDiagnostics :: STMDiagnosticStore
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.
@@ -503,8 +503,8 @@ shakeOpen lspEnv defaultConfig logger debouncer
503503
shakeExtras <- do
504504
globals <- newVar HMap.empty
505505
state <- STM.newIO
506-
diagnostics <- newVar mempty
507-
hiddenDiagnostics <- newVar mempty
506+
diagnostics <- STM.newIO
507+
hiddenDiagnostics <- STM.newIO
508508
publishedDiagnostics <- STM.newIO
509509
positionMapping <- newVar HMap.empty
510510
knownTargetsVar <- newVar $ hashed HMap.empty
@@ -752,13 +752,11 @@ instantiateDelayedAction (DelayedAction _ s p a) = do
752752

753753
getDiagnostics :: IdeState -> IO [FileDiagnostic]
754754
getDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} = do
755-
val <- readVar diagnostics
756-
return $ getAllDiagnostics val
755+
atomically $ getAllDiagnostics diagnostics
757756

758757
getHiddenDiagnostics :: IdeState -> IO [FileDiagnostic]
759758
getHiddenDiagnostics IdeState{shakeExtras = ShakeExtras{hiddenDiagnostics}} = do
760-
val <- readVar hiddenDiagnostics
761-
return $ getAllDiagnostics val
759+
atomically $ getAllDiagnostics hiddenDiagnostics
762760

763761
-- | Find and release old keys from the state Hashmap
764762
-- For the record, there are other state sources that this process does not release:
@@ -1148,17 +1146,14 @@ updateFileDiagnostics fp k ShakeExtras{logger, diagnostics, hiddenDiagnostics, p
11481146
let (currentShown, currentHidden) = partition ((== ShowDiag) . fst) current
11491147
uri = filePathToUri' fp
11501148
ver = vfsVersion =<< modTime
1151-
update new store =
1152-
let store' = setStageDiagnostics uri ver (T.pack $ show k) new store
1153-
new' = getUriDiagnostics uri store'
1154-
in (store', new')
1149+
update new store = setStageDiagnostics uri ver (T.pack $ show k) new store
11551150
mask_ $ do
11561151
-- Mask async exceptions to ensure that updated diagnostics are always
11571152
-- published. Otherwise, we might never publish certain diagnostics if
11581153
-- an exception strikes between modifyVar but before
11591154
-- publishDiagnosticsNotification.
1160-
newDiags <- modifyVar diagnostics $ pure . update (map snd currentShown)
1161-
_ <- modifyVar hiddenDiagnostics $ pure . update (map snd currentHidden)
1155+
newDiags <- liftIO $ atomically $ update (map snd currentShown) diagnostics
1156+
_ <- liftIO $ atomically $ update (map snd currentHidden) hiddenDiagnostics
11621157
let uri = filePathToUri' fp
11631158
let delay = if null newDiags then 0.1 else 0
11641159
registerEvent debouncer delay uri $ do
@@ -1185,10 +1180,21 @@ actionLogger = do
11851180
ShakeExtras{logger} <- getShakeExtras
11861181
return logger
11871182

1183+
--------------------------------------------------------------------------------
1184+
type STMDiagnosticStore = STM.Map NormalizedUri StoreItem
11881185

11891186
getDiagnosticsFromStore :: StoreItem -> [Diagnostic]
11901187
getDiagnosticsFromStore (StoreItem _ diags) = concatMap SL.fromSortedList $ Map.elems diags
11911188

1189+
updateSTMDiagnostics :: STMDiagnosticStore
1190+
-> NormalizedUri -> TextDocumentVersion -> DiagnosticsBySource
1191+
-> STM [LSP.Diagnostic]
1192+
updateSTMDiagnostics store uri mv newDiagsBySource =
1193+
getDiagnosticsFromStore . fromJust <$> STM.focus (Focus.alter update *> Focus.lookup) uri store
1194+
where
1195+
update (Just(StoreItem mvs dbs))
1196+
| mvs == mv = Just (StoreItem mv (newDiagsBySource <> dbs))
1197+
update _ = Just (StoreItem mv newDiagsBySource)
11921198

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

12061212
getAllDiagnostics ::
1207-
DiagnosticStore ->
1208-
[FileDiagnostic]
1213+
STMDiagnosticStore ->
1214+
STM [FileDiagnostic]
12091215
getAllDiagnostics =
1210-
concatMap (\(k,v) -> map (fromUri k,ShowDiag,) $ getDiagnosticsFromStore v) . HMap.toList
1211-
1212-
getUriDiagnostics ::
1213-
NormalizedUri ->
1214-
DiagnosticStore ->
1215-
[LSP.Diagnostic]
1216-
getUriDiagnostics uri ds =
1217-
maybe [] getDiagnosticsFromStore $
1218-
HMap.lookup uri ds
1216+
fmap (concatMap (\(k,v) -> map (fromUri k,ShowDiag,) $ getDiagnosticsFromStore v)) . ListT.toList . STM.listT
12191217

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

0 commit comments

Comments
 (0)