Skip to content

Commit 21a14f3

Browse files
committed
lockless FileExistsMap
1 parent b7d5816 commit 21a14f3

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ module Development.IDE.Core.FileExists
1010
)
1111
where
1212

13-
import Control.Concurrent.Strict
13+
import Control.Concurrent.STM (atomically)
1414
import Control.Exception
1515
import Control.Monad.Extra
1616
import Control.Monad.IO.Class
1717
import qualified Data.ByteString as BS
18-
import Data.HashMap.Strict (HashMap)
19-
import qualified Data.HashMap.Strict as HashMap
2018
import Data.List (partition)
2119
import Data.Maybe
2220
import Development.IDE.Core.FileStore
@@ -26,9 +24,11 @@ import Development.IDE.Core.Shake
2624
import Development.IDE.Graph
2725
import Development.IDE.Types.Location
2826
import Development.IDE.Types.Options
27+
import qualified Focus
2928
import Ide.Plugin.Config (Config)
3029
import Language.LSP.Server hiding (getVirtualFile)
3130
import Language.LSP.Types
31+
import qualified StmContainers.Map as STM
3232
import qualified System.Directory as Dir
3333
import qualified System.FilePath.Glob as Glob
3434

@@ -74,32 +74,34 @@ fast path by a check that the path also matches our watching patterns.
7474
-- | A map for tracking the file existence.
7575
-- If a path maps to 'True' then it exists; if it maps to 'False' then it doesn't exist'; and
7676
-- if it's not in the map then we don't know.
77-
type FileExistsMap = (HashMap NormalizedFilePath Bool)
77+
type FileExistsMap = STM.Map NormalizedFilePath Bool
7878

7979
-- | A wrapper around a mutable 'FileExistsState'
80-
newtype FileExistsMapVar = FileExistsMapVar (Var FileExistsMap)
80+
newtype FileExistsMapVar = FileExistsMapVar FileExistsMap
8181

8282
instance IsIdeGlobal FileExistsMapVar
8383

8484
-- | Grab the current global value of 'FileExistsMap' without acquiring a dependency
8585
getFileExistsMapUntracked :: Action FileExistsMap
8686
getFileExistsMapUntracked = do
8787
FileExistsMapVar v <- getIdeGlobalAction
88-
liftIO $ readVar v
88+
return v
8989

9090
-- | Modify the global store of file exists.
9191
modifyFileExists :: IdeState -> [(NormalizedFilePath, FileChangeType)] -> IO ()
9292
modifyFileExists state changes = do
9393
FileExistsMapVar var <- getIdeGlobalState state
94-
changesMap <- evaluate $ HashMap.fromList changes
9594
-- Masked to ensure that the previous values are flushed together with the map update
9695
mask $ \_ -> do
9796
-- update the map
98-
void $ modifyVar' var $ HashMap.union (HashMap.mapMaybe fromChange changesMap)
97+
void $ atomically $ forM_ changes $ \(f,c) ->
98+
case fromChange c of
99+
Just c' -> STM.focus (Focus.insert c') f var
100+
Nothing -> pure ()
99101
-- See Note [Invalidating file existence results]
100102
-- flush previous values
101103
let (fileModifChanges, fileExistChanges) =
102-
partition ((== FcChanged) . snd) (HashMap.toList changesMap)
104+
partition ((== FcChanged) . snd) changes
103105
mapM_ (deleteValue (shakeExtras state) GetFileExists . fst) fileExistChanges
104106
recordDirtyKeys (shakeExtras state) GetFileExists $ map fst fileExistChanges
105107
recordDirtyKeys (shakeExtras state) GetModificationTime $ map fst fileModifChanges
@@ -161,7 +163,7 @@ fileExistsRules lspEnv vfs = do
161163
-- Create the global always, although it should only be used if we have fast rules.
162164
-- But there's a chance someone will send unexpected notifications anyway,
163165
-- e.g. https://github.com/haskell/ghcide/issues/599
164-
addIdeGlobal . FileExistsMapVar =<< liftIO (newVar [])
166+
addIdeGlobal . FileExistsMapVar =<< liftIO STM.newIO
165167

166168
extras <- getShakeExtrasRules
167169
opts <- liftIO $ getIdeOptionsIO extras
@@ -210,7 +212,7 @@ fileExistsFast vfs file = do
210212
-- Could in principle use 'alwaysRerun' here, but it's too slwo, See Note [Invalidating file existence results]
211213
mp <- getFileExistsMapUntracked
212214

213-
let mbFilesWatched = HashMap.lookup file mp
215+
mbFilesWatched <- liftIO $ atomically $ STM.lookup file mp
214216
exist <- case mbFilesWatched of
215217
Just exist -> pure exist
216218
-- We don't know about it: use the slow route.

0 commit comments

Comments
 (0)