@@ -169,57 +169,57 @@ func compileFilesWithRecipe(ctx *types.Context, sourcePath *paths.Path, sources
169
169
if len (sources ) == 0 {
170
170
return objectFiles , nil
171
171
}
172
- objectFilesChan := make ( chan * paths. Path )
173
- errorsChan := make ( chan error )
174
- doneChan := make ( chan struct {})
172
+ var objectFilesMux sync. Mutex
173
+ var errors [] error
174
+ var errorsMux sync. Mutex
175
175
176
176
ctx .Progress .Steps = ctx .Progress .Steps / float64 (len (sources ))
177
- var wg sync.WaitGroup
178
177
179
- // Split jobs into batches of N jobs each; wait for the completion of a batch to start the next
180
- par := ctx .Jobs
181
-
182
- go func () {
183
- for total := 0 ; total < len (sources ); total += par {
184
- for i := total ; i < total + par && i < len (sources ); i ++ {
185
- wg .Add (1 )
186
- go func (source * paths.Path ) {
187
- defer wg .Done ()
188
- PrintProgressIfProgressEnabledAndMachineLogger (ctx )
189
- objectFile , err := compileFileWithRecipe (ctx , sourcePath , source , buildPath , buildProperties , includes , recipe )
190
- if err != nil {
191
- errorsChan <- err
192
- } else {
193
- objectFilesChan <- objectFile
194
- }
195
- }(sources [i ])
196
- }
197
- wg .Wait ()
178
+ queue := make (chan * paths.Path )
179
+ job := func (source * paths.Path ) {
180
+ PrintProgressIfProgressEnabledAndMachineLogger (ctx )
181
+ objectFile , err := compileFileWithRecipe (ctx , sourcePath , source , buildPath , buildProperties , includes , recipe )
182
+ if err != nil {
183
+ errorsMux .Lock ()
184
+ errors = append (errors , err )
185
+ errorsMux .Unlock ()
186
+ } else {
187
+ objectFilesMux .Lock ()
188
+ objectFiles .Add (objectFile )
189
+ objectFilesMux .Unlock ()
198
190
}
191
+ }
199
192
200
- doneChan <- struct {}{}
201
- }()
202
-
203
- go func () {
204
- wg .Wait ()
205
- doneChan <- struct {}{}
206
- }()
207
-
208
- for {
209
- select {
210
- case objectFile := <- objectFilesChan :
211
- objectFiles .Add (objectFile )
212
- case err := <- errorsChan :
213
- return nil , i18n .WrapError (err )
214
- case <- doneChan :
215
- close (objectFilesChan )
216
- for objectFile := range objectFilesChan {
217
- objectFiles .Add (objectFile )
193
+ // Spawn jobs runners
194
+ var wg sync.WaitGroup
195
+ for i := 0 ; i < ctx .Jobs ; i ++ {
196
+ wg .Add (1 )
197
+ go func () {
198
+ for source := range queue {
199
+ job (source )
218
200
}
219
- objectFiles .Sort ()
220
- return objectFiles , nil
201
+ wg .Done ()
202
+ }()
203
+ }
204
+
205
+ // Feed jobs until error or done
206
+ for _ , source := range sources {
207
+ errorsMux .Lock ()
208
+ gotError := len (errors ) > 0
209
+ errorsMux .Unlock ()
210
+ if gotError {
211
+ break
221
212
}
213
+ queue <- source
214
+ }
215
+ close (queue )
216
+ wg .Wait ()
217
+ if len (errors ) > 0 {
218
+ // output the first error
219
+ return nil , i18n .WrapError (errors [0 ])
222
220
}
221
+ objectFiles .Sort ()
222
+ return objectFiles , nil
223
223
}
224
224
225
225
func compileFileWithRecipe (ctx * types.Context , sourcePath * paths.Path , source * paths.Path , buildPath * paths.Path , buildProperties * properties.Map , includes []string , recipe string ) (* paths.Path , error ) {
0 commit comments