1- {-# LANGUAGE NoImplicitPrelude #-}
2- {-# LANGUAGE OverloadedRecordDot #-}
1+ {-# LANGUAGE NoImplicitPrelude #-}
2+ {-# LANGUAGE DuplicateRecordFields #-}
3+ {-# LANGUAGE NoFieldSelectors #-}
4+ {-# LANGUAGE OverloadedRecordDot #-}
35
46-- Concurrent execution with dependencies. Types currently hard-coded for needs
57-- of stack, but could be generalized easily.
@@ -55,9 +57,9 @@ data Action = Action
5557 -- ^ The action's unique id.
5658 , actionDeps :: ! (Set ActionId )
5759 -- ^ Actions on which this action depends.
58- , actionDo :: ! (ActionContext -> IO () )
60+ , action :: ! (ActionContext -> IO () )
5961 -- ^ The action's 'IO' action, given a context.
60- , actionConcurrency :: ! Concurrency
62+ , concurrency :: ! Concurrency
6163 -- ^ Whether this action may be run concurrently with others.
6264 }
6365
@@ -69,20 +71,20 @@ data Concurrency
6971 deriving Eq
7072
7173data ActionContext = ActionContext
72- { acRemaining :: ! (Set ActionId )
74+ { remaining :: ! (Set ActionId )
7375 -- ^ Does not include the current action.
74- , acDownstream :: [Action ]
76+ , downstream :: [Action ]
7577 -- ^ Actions which depend on the current action.
76- , acConcurrency :: ! Concurrency
78+ , concurrency :: ! Concurrency
7779 -- ^ Whether this action may be run concurrently with others.
7880 }
7981
8082data ExecuteState = ExecuteState
81- { esActions :: TVar [Action ]
82- , esExceptions :: TVar [SomeException ]
83- , esInAction :: TVar (Set ActionId )
84- , esCompleted :: TVar Int
85- , esKeepGoing :: Bool
83+ { actions :: TVar [Action ]
84+ , exceptions :: TVar [SomeException ]
85+ , inAction :: TVar (Set ActionId )
86+ , completed :: TVar Int
87+ , keepGoing :: Bool
8688 }
8789
8890runActions ::
@@ -98,16 +100,16 @@ runActions threads keepGoing actions withProgress = do
98100 <*> newTVarIO Set. empty -- esInAction
99101 <*> newTVarIO 0 -- esCompleted
100102 <*> pure keepGoing -- esKeepGoing
101- _ <- async $ withProgress es. esCompleted es. esInAction
103+ _ <- async $ withProgress es. completed es. inAction
102104 if threads <= 1
103105 then runActions' es
104106 else replicateConcurrently_ threads $ runActions' es
105- readTVarIO es. esExceptions
107+ readTVarIO es. exceptions
106108
107109-- | Sort actions such that those that can't be run concurrently are at
108110-- the end.
109111sortActions :: [Action ] -> [Action ]
110- sortActions = sortBy (compareConcurrency `on` (. actionConcurrency ))
112+ sortActions = sortBy (compareConcurrency `on` (. concurrency ))
111113 where
112114 -- NOTE: Could derive Ord. However, I like to make this explicit so
113115 -- that changes to the datatype must consider how it's affecting
@@ -124,53 +126,54 @@ runActions' es = loop
124126
125127 breakOnErrs :: STM (IO () ) -> STM (IO () )
126128 breakOnErrs inner = do
127- errs <- readTVar es. esExceptions
128- if null errs || es. esKeepGoing
129+ errs <- readTVar es. exceptions
130+ if null errs || es. keepGoing
129131 then inner
130132 else doNothing
131133
132134 withActions :: ([Action ] -> STM (IO () )) -> STM (IO () )
133135 withActions inner = do
134- actions <- readTVar es. esActions
136+ actions <- readTVar es. actions
135137 if null actions
136138 then doNothing
137139 else inner actions
138140
139141 processActions :: [Action ] -> STM (IO () )
140142 processActions actions = do
141- inAction <- readTVar es. esInAction
143+ inAction <- readTVar es. inAction
142144 case break (Set. null . (. actionDeps)) actions of
143145 (_, [] ) -> do
144146 check (Set. null inAction)
145- unless es. esKeepGoing $
146- modifyTVar es. esExceptions (toException InconsistentDependenciesBug : )
147+ unless es. keepGoing $
148+ modifyTVar es. exceptions (toException InconsistentDependenciesBug : )
147149 doNothing
148150 (xs, action: ys) -> processAction inAction (xs ++ ys) action
149151
150152 processAction :: Set ActionId -> [Action ] -> Action -> STM (IO () )
151153 processAction inAction otherActions action = do
152- let concurrency = action. actionConcurrency
154+ let concurrency = action. concurrency
153155 unless (concurrency == ConcurrencyAllowed ) $
154156 check (Set. null inAction)
155157 let action' = action. actionId
156158 otherActions' = Set. fromList $ map (. actionId) otherActions
157159 remaining = Set. union otherActions' inAction
160+ downstream = downstreamActions action' otherActions
158161 actionContext = ActionContext
159- { acRemaining = remaining
160- , acDownstream = downstreamActions action' otherActions
161- , acConcurrency = concurrency
162+ { remaining
163+ , downstream
164+ , concurrency
162165 }
163- writeTVar es. esActions otherActions
164- modifyTVar es. esInAction (Set. insert action')
166+ writeTVar es. actions otherActions
167+ modifyTVar es. inAction (Set. insert action')
165168 pure $ do
166169 mask $ \ restore -> do
167- eres <- try $ restore $ action. actionDo actionContext
170+ eres <- try $ restore $ action. action actionContext
168171 atomically $ do
169- modifyTVar es. esInAction (Set. delete action')
170- modifyTVar es. esCompleted (+ 1 )
172+ modifyTVar es. inAction (Set. delete action')
173+ modifyTVar es. completed (+ 1 )
171174 case eres of
172- Left err -> modifyTVar es. esExceptions (err: )
173- Right () -> modifyTVar es. esActions $ map (dropDep action')
175+ Left err -> modifyTVar es. exceptions (err: )
176+ Right () -> modifyTVar es. actions $ map (dropDep action')
174177 loop
175178
176179 -- | Filter a list of actions to include only those that depend on the given
0 commit comments