Skip to content

Commit 7f8fb33

Browse files
committed
Fix progressbar
Port of arduino/arduino-builder#289
1 parent f3b7f0a commit 7f8fb33

File tree

4 files changed

+68
-62
lines changed

4 files changed

+68
-62
lines changed

Diff for: legacy/builder/builder.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func (s *PreprocessSketch) Run(ctx *types.Context) error {
143143
} else {
144144
commands = append(commands, &ContainerAddPrototypes{})
145145
}
146-
return runCommands(ctx, commands, true)
146+
return runCommands(ctx, commands, false)
147147
}
148148

149149
type Preprocess struct{}
@@ -201,12 +201,12 @@ func (s *ParseHardwareAndDumpBuildProperties) Run(ctx *types.Context) error {
201201
func runCommands(ctx *types.Context, commands []types.Command, progressEnabled bool) error {
202202

203203
ctx.Progress.PrintEnabled = progressEnabled
204-
ctx.Progress.Progress = 0
205204

206205
for _, command := range commands {
207206
PrintRingNameIfDebug(ctx, command)
208-
ctx.Progress.Steps = 100.0 / float64(len(commands))
209-
builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx)
207+
stepSize := float64(100-(6*len(ctx.ImportedLibraries))) / float64(len(commands))
208+
ctx.Progress.Steps = stepSize
209+
builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx, progressEnabled, stepSize)
210210
err := command.Run(ctx)
211211
if err != nil {
212212
return i18n.WrapError(err)

Diff for: legacy/builder/builder_utils/utils.go

+51-52
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import (
3333
"os"
3434
"os/exec"
3535
"path/filepath"
36-
"runtime"
3736
"strconv"
3837
"strings"
3938
"sync"
@@ -46,16 +45,20 @@ import (
4645
"github.com/arduino/go-properties-orderedmap"
4746
)
4847

49-
func PrintProgressIfProgressEnabledAndMachineLogger(ctx *types.Context) {
48+
func PrintProgressIfProgressEnabledAndMachineLogger(ctx *types.Context, progressEnabled bool, stepSize float64) {
5049

51-
if !ctx.Progress.PrintEnabled {
50+
var mut sync.Mutex
51+
if !progressEnabled {
5252
return
5353
}
5454

5555
log := ctx.GetLogger()
5656
if log.Name() == "machine" {
57+
mut.Lock()
5758
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()
5962
}
6063
}
6164

@@ -170,61 +173,57 @@ func compileFilesWithRecipe(ctx *types.Context, sourcePath *paths.Path, sources
170173
if len(sources) == 0 {
171174
return objectFiles, nil
172175
}
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{})
176179

177-
ctx.Progress.Steps = ctx.Progress.Steps / float64(len(sources))
180+
stepSize := ctx.Progress.Steps / float64(len(sources))
181+
var wg sync.WaitGroup
178182

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()
191202
}
192-
}
193203

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+
}()
209211

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
217225
}
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])
225226
}
226-
objectFiles.Sort()
227-
return objectFiles, nil
228227
}
229228

230229
func compileFileWithRecipe(ctx *types.Context, sourcePath *paths.Path, source *paths.Path, buildPath *paths.Path, buildProperties *properties.Map, includes []string, recipe string) (*paths.Path, error) {

Diff for: legacy/builder/container_find_includes.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,11 @@ func (s *ContainerFindIncludes) Run(ctx *types.Context) error {
148148
queueSourceFilesFromFolder(ctx, sourceFilePaths, sketch, srcSubfolderPath, true /* recurse */)
149149
}
150150

151+
stepSize := ctx.Progress.Steps / 20.0
152+
stepLimit := ctx.Progress.Progress + ctx.Progress.Steps
153+
151154
for !sourceFilePaths.Empty() {
152-
err := findIncludesUntilDone(ctx, cache, sourceFilePaths.Pop())
155+
err := findIncludesUntilDone(ctx, cache, sourceFilePaths.Pop(), stepSize, stepLimit)
153156
if err != nil {
154157
cachePath.Remove()
155158
return i18n.WrapError(err)
@@ -290,7 +293,7 @@ func writeCache(cache *includeCache, path *paths.Path) error {
290293
return nil
291294
}
292295

293-
func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile types.SourceFile) error {
296+
func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile types.SourceFile, stepSize, stepLimit float64) error {
294297
sourcePath := sourceFile.SourcePath(ctx)
295298
targetFilePath := paths.NullPath()
296299
depPath := sourceFile.DepfilePath(ctx)
@@ -318,6 +321,8 @@ func findIncludesUntilDone(ctx *types.Context, cache *includeCache, sourceFile t
318321
var include string
319322
cache.ExpectFile(sourcePath)
320323

324+
go builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx, ctx.Progress.Progress < stepLimit, stepSize)
325+
321326
includes := ctx.IncludeFolders
322327
if library, ok := sourceFile.Origin.(*libraries.Library); ok && library.UtilityDir != nil {
323328
includes = append(includes, library.UtilityDir)

Diff for: legacy/builder/container_setup.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ func (s *ContainerSetupHardwareToolsLibsSketchAndProps) Run(ctx *types.Context)
5252
&LibrariesLoader{},
5353
}
5454

55-
ctx.Progress.Steps = ctx.Progress.Steps / float64(len(commands))
55+
stepSize := ctx.Progress.Steps / float64(len(commands))
56+
ctx.Progress.Steps = stepSize
5657

5758
for _, command := range commands {
58-
builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx)
59+
builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx, ctx.Progress.PrintEnabled, stepSize)
5960
PrintRingNameIfDebug(ctx, command)
6061
err := command.Run(ctx)
6162
if err != nil {
@@ -84,10 +85,11 @@ func (s *ContainerSetupHardwareToolsLibsSketchAndProps) Run(ctx *types.Context)
8485
&AddMissingBuildPropertiesFromParentPlatformTxtFiles{},
8586
}
8687

87-
ctx.Progress.Steps = ctx.Progress.Steps / float64(len(commands))
88+
stepSize = ctx.Progress.Steps / float64(len(commands))
89+
ctx.Progress.Steps = stepSize
8890

8991
for _, command := range commands {
90-
builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx)
92+
builder_utils.PrintProgressIfProgressEnabledAndMachineLogger(ctx, ctx.Progress.PrintEnabled, stepSize)
9193
PrintRingNameIfDebug(ctx, command)
9294
err := command.Run(ctx)
9395
if err != nil {

0 commit comments

Comments
 (0)