@@ -33,7 +33,6 @@ import (
33
33
"os"
34
34
"os/exec"
35
35
"path/filepath"
36
- "runtime"
37
36
"strconv"
38
37
"strings"
39
38
"sync"
@@ -46,16 +45,20 @@ import (
46
45
"github.com/arduino/go-properties-orderedmap"
47
46
)
48
47
49
- func PrintProgressIfProgressEnabledAndMachineLogger (ctx * types.Context ) {
48
+ func PrintProgressIfProgressEnabledAndMachineLogger (ctx * types.Context , progressEnabled bool , stepSize float64 ) {
50
49
51
- if ! ctx .Progress .PrintEnabled {
50
+ var mut sync.Mutex
51
+ if ! progressEnabled {
52
52
return
53
53
}
54
54
55
55
log := ctx .GetLogger ()
56
56
if log .Name () == "machine" {
57
+ mut .Lock ()
57
58
log .Println (constants .LOG_LEVEL_INFO , constants .MSG_PROGRESS , strconv .FormatFloat (ctx .Progress .Progress , 'f' , 2 , 32 ))
58
- ctx .Progress .Progress += ctx .Progress .Steps
59
+ ctx .Progress .Progress += stepSize
60
+ log .Flush ()
61
+ mut .Unlock ()
59
62
}
60
63
}
61
64
@@ -170,61 +173,57 @@ func compileFilesWithRecipe(ctx *types.Context, sourcePath *paths.Path, sources
170
173
if len (sources ) == 0 {
171
174
return objectFiles , nil
172
175
}
173
- var objectFilesMux sync. Mutex
174
- var errors [] error
175
- var errorsMux sync. Mutex
176
+ objectFilesChan := make ( chan * paths. Path )
177
+ errorsChan := make ( chan error )
178
+ doneChan := make ( chan struct {})
176
179
177
- ctx .Progress .Steps = ctx .Progress .Steps / float64 (len (sources ))
180
+ stepSize := ctx .Progress .Steps / float64 (len (sources ))
181
+ var wg sync.WaitGroup
178
182
179
- queue := make (chan * paths.Path )
180
- job := func (source * paths.Path ) {
181
- PrintProgressIfProgressEnabledAndMachineLogger (ctx )
182
- objectFile , err := compileFileWithRecipe (ctx , sourcePath , source , buildPath , buildProperties , includes , recipe )
183
- if err != nil {
184
- errorsMux .Lock ()
185
- errors = append (errors , err )
186
- errorsMux .Unlock ()
187
- } else {
188
- objectFilesMux .Lock ()
189
- objectFiles .Add (objectFile )
190
- objectFilesMux .Unlock ()
183
+ // Split jobs into batches of N jobs each; wait for the completion of a batch to start the next
184
+ par := ctx .Jobs
185
+
186
+ go func () {
187
+ for total := 0 ; total < len (sources ); total += par {
188
+ for i := total ; i < total + par && i < len (sources ); i ++ {
189
+ wg .Add (1 )
190
+ go func (source * paths.Path ) {
191
+ defer wg .Done ()
192
+ go PrintProgressIfProgressEnabledAndMachineLogger (ctx , true , stepSize )
193
+ objectFile , err := compileFileWithRecipe (ctx , sourcePath , source , buildPath , buildProperties , includes , recipe )
194
+ if err != nil {
195
+ errorsChan <- err
196
+ } else {
197
+ objectFilesChan <- objectFile
198
+ }
199
+ }(sources [i ])
200
+ }
201
+ wg .Wait ()
191
202
}
192
- }
193
203
194
- // Spawn jobs runners
195
- var wg sync.WaitGroup
196
- jobs := ctx .Jobs
197
- if jobs == 0 {
198
- jobs = runtime .NumCPU ()
199
- }
200
- for i := 0 ; i < jobs ; i ++ {
201
- wg .Add (1 )
202
- go func () {
203
- for source := range queue {
204
- job (source )
205
- }
206
- wg .Done ()
207
- }()
208
- }
204
+ doneChan <- struct {}{}
205
+ }()
206
+
207
+ go func () {
208
+ wg .Wait ()
209
+ doneChan <- struct {}{}
210
+ }()
209
211
210
- // Feed jobs until error or done
211
- for _ , source := range sources {
212
- errorsMux .Lock ()
213
- gotError := len (errors ) > 0
214
- errorsMux .Unlock ()
215
- if gotError {
216
- break
212
+ for {
213
+ select {
214
+ case objectFile := <- objectFilesChan :
215
+ objectFiles .Add (objectFile )
216
+ case err := <- errorsChan :
217
+ return nil , i18n .WrapError (err )
218
+ case <- doneChan :
219
+ close (objectFilesChan )
220
+ for objectFile := range objectFilesChan {
221
+ objectFiles .Add (objectFile )
222
+ }
223
+ objectFiles .Sort ()
224
+ return objectFiles , nil
217
225
}
218
- queue <- source
219
- }
220
- close (queue )
221
- wg .Wait ()
222
- if len (errors ) > 0 {
223
- // output the first error
224
- return nil , i18n .WrapError (errors [0 ])
225
226
}
226
- objectFiles .Sort ()
227
- return objectFiles , nil
228
227
}
229
228
230
229
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