1
1
-- We deliberately want to ensure the function we add to the rule database
2
2
-- has the constraints we need on it when we get it out.
3
3
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
4
- {-# LANGUAGE LambdaCase #-}
4
+ {-# LANGUAGE LambdaCase #-}
5
+ {-# LANGUAGE NamedFieldPuns #-}
6
+ {-# LANGUAGE RecordWildCards #-}
5
7
{-# LANGUAGE ScopedTypeVariables #-}
6
- {-# LANGUAGE RecordWildCards #-}
7
- {-# LANGUAGE TypeFamilies #-}
8
- {-# LANGUAGE TupleSections #-}
9
- {-# LANGUAGE NamedFieldPuns #-}
8
+ {-# LANGUAGE TupleSections #-}
9
+ {-# LANGUAGE TypeFamilies #-}
10
10
11
11
module Development.IDE.Graph.Internal.Database where
12
12
13
- import Development.IDE.Graph.Internal.Intern
14
- import Development.IDE.Graph.Internal.Types
15
- import Data.Dynamic
13
+ import Control.Concurrent.Async
14
+ import Control.Concurrent.Extra
15
+ import Control.Exception
16
+ import Control.Monad
17
+ import Control.Monad.Trans.Reader
18
+ import Data.Dynamic
19
+ import Data.Either
20
+ import Data.IORef.Extra
21
+ import Data.Maybe
22
+ import Data.Tuple.Extra
23
+ import qualified Development.IDE.Graph.Internal.Ids as Ids
24
+ import Development.IDE.Graph.Internal.Intern
16
25
import qualified Development.IDE.Graph.Internal.Intern as Intern
17
- import qualified Development.IDE.Graph.Internal.Ids as Ids
18
- import Control.Concurrent.Extra
19
- import Data.IORef.Extra
20
- import Control.Monad
21
- import Development.Shake.Classes
22
- import qualified Development.Shake as Shake
23
- import Data.Maybe
24
- import Control.Concurrent.Async
25
- import System.IO.Unsafe
26
- import Development.IDE.Graph.Internal.Rules
27
- import qualified Development.Shake.Rule as Shake
28
- import Control.Exception
29
- import Control.Monad.Trans.Reader
30
- import Data.Tuple.Extra
31
- import Data.Either
26
+ import Development.IDE.Graph.Internal.Rules
27
+ import Development.IDE.Graph.Internal.Types
28
+ import qualified Development.Shake as Shake
29
+ import Development.Shake.Classes
30
+ import qualified Development.Shake.Rule as Shake
31
+ import System.IO.Unsafe
32
32
33
33
newDatabase :: Dynamic -> TheRules -> IO Database
34
34
newDatabase databaseExtra databaseRules = do
@@ -38,15 +38,17 @@ newDatabase databaseExtra databaseRules = do
38
38
databaseValues <- Ids. empty
39
39
pure Database {.. }
40
40
41
+ -- | Increment the step and mark all ids dirty
41
42
incDatabase :: Database -> IO ()
42
43
incDatabase db = do
43
44
modifyIORef' (databaseStep db) $ \ (Step i) -> Step $ i + 1
44
45
Ids. forMutate (databaseValues db) $ second $ \ case
45
- Clean x -> Dirty (Just x)
46
- Dirty x -> Dirty x
46
+ Clean x -> Dirty (Just x)
47
+ Dirty x -> Dirty x
47
48
Running _ x -> Dirty x
48
49
49
50
51
+ -- | Unwrap and build a list of keys in parallel
50
52
build
51
53
:: forall key value . (Shake. RuleResult key ~ value , Typeable key , Show key , Hashable key , Eq key , Typeable value )
52
54
=> Database -> [key ] -> IO ([Id ], [value ])
@@ -57,6 +59,7 @@ build db keys = do
57
59
asV :: Value -> value
58
60
asV (Value x) = unwrapDynamic x
59
61
62
+ -- | Build a list of keys in parallel
60
63
builder
61
64
:: Database -> [Either Id Key ] -> IO [(Id , Result )]
62
65
builder db@ Database {.. } keys = do
@@ -69,6 +72,7 @@ builder db@Database{..} keys = do
69
72
70
73
results <- withLock databaseLock $ do
71
74
forM keys $ \ idKey -> do
75
+ -- Resolve the id
72
76
id <- case idKey of
73
77
Left id -> pure id
74
78
Right key -> do
@@ -80,6 +84,7 @@ builder db@Database{..} keys = do
80
84
writeIORef' databaseIds ids
81
85
return id
82
86
87
+ -- Spawn the id if needed
83
88
status <- Ids. lookup databaseValues id
84
89
val <- case fromMaybe (fromRight undefined idKey, Dirty Nothing ) status of
85
90
(_, Clean r) -> pure r
@@ -111,7 +116,7 @@ cleanupAsync :: IORef [Async a] -> IO ()
111
116
cleanupAsync ref = mapConcurrently_ uninterruptibleCancel =<< readIORef ref
112
117
113
118
114
- -- Check if we need to run the database.
119
+ -- | Check if we need to run the database.
115
120
check :: Database -> Key -> Id -> Maybe Result -> IO Result
116
121
check db key id result@ (Just me@ Result {resultDeps= Just deps}) = do
117
122
res <- builder db $ map Left deps
@@ -121,7 +126,7 @@ check db key id result@(Just me@Result{resultDeps=Just deps}) = do
121
126
check db key id result = spawn db key id Shake. RunDependenciesChanged result
122
127
123
128
124
- -- Spawn a new computation to run the action.
129
+ -- | Spawn a new computation to run the action.
125
130
spawn :: Database -> Key -> Id -> Shake. RunMode -> Maybe Result -> IO Result
126
131
spawn db@ Database {.. } key id mode result = do
127
132
let act = runRule databaseRules key (fmap resultData result) mode
@@ -137,6 +142,7 @@ spawn db@Database{..} key id mode result = do
137
142
138
143
data Box a = Box { fromBox :: a }
139
144
145
+ -- | Split an IO computation into an unsafe lazy value and a forcing computation
140
146
splitIO :: IO a -> (IO () , a )
141
147
splitIO act = do
142
148
let act2 = Box <$> act
0 commit comments