@@ -29,12 +29,12 @@ import Data.IntSet (IntSet)
29
29
import qualified Data.IntSet as Set
30
30
import Data.Maybe
31
31
import Data.Tuple.Extra
32
+ import Development.IDE.Graph.Classes
32
33
import qualified Development.IDE.Graph.Internal.Ids as Ids
33
34
import Development.IDE.Graph.Internal.Intern
34
35
import qualified Development.IDE.Graph.Internal.Intern as Intern
35
36
import Development.IDE.Graph.Internal.Rules
36
37
import Development.IDE.Graph.Internal.Types
37
- import Development.IDE.Graph.Classes
38
38
import System.IO.Unsafe
39
39
import System.Time.Extra (duration )
40
40
@@ -57,8 +57,8 @@ incDatabase db Nothing = do
57
57
writeIORef (databaseDirtySet db) Nothing
58
58
withLock (databaseLock db) $
59
59
Ids. forMutate (databaseValues db) $ \ _ -> second $ \ case
60
- Clean x -> Dirty (Just x)
61
- Dirty x -> Dirty x
60
+ Clean x -> Dirty (Just x)
61
+ Dirty x -> Dirty x
62
62
Running _ _ x -> Dirty x
63
63
-- only some keys are dirty
64
64
incDatabase db (Just kk) = do
@@ -126,25 +126,13 @@ builder db@Database{..} keys = do
126
126
pure (id , val)
127
127
128
128
toForceList <- liftIO $ readIORef toForce
129
+ waitAll <- unliftAIO $ mapConcurrentlyAIO_ sequence_ $ increasingChunks toForceList
129
130
case toForceList of
130
131
[] -> return $ Left results
131
132
_ -> return $ Right $ do
132
- parallelWait toForceList
133
+ waitAll
133
134
pure results
134
135
135
- parallelWait :: [IO () ] -> IO ()
136
- parallelWait [] = pure ()
137
- parallelWait [one] = one
138
- parallelWait many = mapConcurrently_ sequence_ (increasingChunks many)
139
-
140
- -- >>> increasingChunks [1..20]
141
- -- [[1,2],[3,4,5,6],[7,8,9,10,11,12,13,14],[15,16,17,18,19,20]]
142
- increasingChunks :: [a ] -> [[a ]]
143
- increasingChunks = go 2 where
144
- go :: Int -> [a ] -> [[a ]]
145
- go _ [] = []
146
- go n xx = let (chunk, rest) = splitAt n xx in chunk : go (min 10 (n* 2 )) rest
147
-
148
136
-- | Refresh a key:
149
137
-- * If no dirty dependencies and we have evaluated the key previously, then we refresh it in the current thread.
150
138
-- This assumes that the implementation will be a lookup
@@ -256,7 +244,7 @@ asyncWithCleanUp act = do
256
244
io <- unliftAIO act
257
245
liftIO $ uninterruptibleMask $ \ restore -> do
258
246
a <- async $ restore io
259
- modifyIORef st (void a : )
247
+ atomicModifyIORef'_ st (void a : )
260
248
return $ wait a
261
249
262
250
withLockAIO :: Lock -> AIO a -> AIO a
@@ -274,3 +262,22 @@ cleanupAsync ref = uninterruptibleMask_ $ do
274
262
asyncs <- readIORef ref
275
263
mapM_ (\ a -> throwTo (asyncThreadId a) AsyncCancelled ) asyncs
276
264
mapM_ waitCatch asyncs
265
+
266
+
267
+ mapConcurrentlyAIO_ :: (a -> IO () ) -> [a ] -> AIO ()
268
+ mapConcurrentlyAIO_ _ [] = pure ()
269
+ mapConcurrentlyAIO_ f [one] = liftIO $ f one
270
+ mapConcurrentlyAIO_ f many = do
271
+ ref <- AIO ask
272
+ liftIO $ uninterruptibleMask $ \ restore -> do
273
+ asyncs <- liftIO $ traverse async (map (restore . f) many)
274
+ liftIO $ atomicModifyIORef'_ ref (asyncs ++ )
275
+ traverse_ wait asyncs
276
+
277
+ -- >>> increasingChunks [1..20]
278
+ -- [[1,2],[3,4,5,6],[7,8,9,10,11,12,13,14],[15,16,17,18,19,20]]
279
+ increasingChunks :: [a ] -> [[a ]]
280
+ increasingChunks = go 2 where
281
+ go :: Int -> [a ] -> [[a ]]
282
+ go _ [] = []
283
+ go n xx = let (chunk, rest) = splitAt n xx in chunk : go (min 10 (n* 2 )) rest
0 commit comments