| 23 | 23 |
toDrop bool
|
| 24 | 24 |
noPop bool
|
| 25 | 25 |
hasEwmaDecorators bool
|
|
26 |
frameCh chan *frame
|
| 26 | 27 |
operateState chan func(*bState)
|
| 27 | |
frameCh chan *frame
|
| 28 | |
|
| 29 | |
// cancel is called either by user or on complete event
|
| 30 | |
cancel func()
|
| 31 | |
// done is closed after cacheState is assigned
|
| 32 | |
done chan struct{}
|
| 33 | |
// cacheState is populated, right after close(b.done)
|
| 34 | |
cacheState *bState
|
| 35 | |
|
| 36 | |
container *Progress
|
| 37 | |
recoveredPanic interface{}
|
|
28 |
done chan struct{}
|
|
29 |
cacheState *bState
|
|
30 |
container *Progress
|
|
31 |
cancel func()
|
|
32 |
recoveredPanic interface{}
|
| 38 | 33 |
}
|
| 39 | 34 |
|
| 40 | 35 |
type extenderFunc func(in io.Reader, reqWidth int, st decor.Statistics) (out io.Reader, lines int)
|
| 41 | 36 |
|
| 42 | |
// bState is actual bar state. It gets passed to *Bar.serve(...) monitor
|
| 43 | |
// goroutine.
|
|
37 |
// bState is actual bar's state.
|
| 44 | 38 |
type bState struct {
|
| 45 | 39 |
id int
|
| 46 | 40 |
priority int
|
|
| 65 | 59 |
filler BarFiller
|
| 66 | 60 |
middleware func(BarFiller) BarFiller
|
| 67 | 61 |
extender extenderFunc
|
| 68 | |
|
| 69 | |
// runningBar is a key for *pState.parkedBars
|
| 70 | |
runningBar *Bar
|
| 71 | |
|
| 72 | |
debugOut io.Writer
|
|
62 |
debugOut io.Writer
|
|
63 |
|
|
64 |
// afterBar is a key for *pState.parkedBars
|
|
65 |
afterBar *Bar
|
| 73 | 66 |
}
|
| 74 | 67 |
|
| 75 | 68 |
type frame struct {
|
|
| 77 | 70 |
lines int
|
| 78 | 71 |
}
|
| 79 | 72 |
|
| 80 | |
func newBar(container *Progress, bs *bState) *Bar {
|
|
73 |
func newBar(container *Progress, bs *bState) (*Bar, func()) {
|
| 81 | 74 |
ctx, cancel := context.WithCancel(container.ctx)
|
| 82 | 75 |
|
| 83 | 76 |
bar := &Bar{
|
| 84 | |
container: container,
|
| 85 | 77 |
priority: bs.priority,
|
| 86 | 78 |
toDrop: bs.dropOnComplete,
|
| 87 | 79 |
noPop: bs.noPop,
|
|
80 |
frameCh: make(chan *frame, 1),
|
| 88 | 81 |
operateState: make(chan func(*bState)),
|
| 89 | |
frameCh: make(chan *frame, 1),
|
| 90 | 82 |
done: make(chan struct{}),
|
|
83 |
container: container,
|
| 91 | 84 |
cancel: cancel,
|
| 92 | 85 |
}
|
| 93 | 86 |
|
| 94 | |
go bar.serve(ctx, bs)
|
| 95 | |
return bar
|
|
87 |
bar.subscribeDecorators(bs)
|
|
88 |
|
|
89 |
serve := func() {
|
|
90 |
defer container.bwg.Done()
|
|
91 |
for {
|
|
92 |
select {
|
|
93 |
case op := <-bar.operateState:
|
|
94 |
op(bs)
|
|
95 |
case <-ctx.Done():
|
|
96 |
bs.decoratorShutdownNotify()
|
|
97 |
bar.cacheState = bs
|
|
98 |
close(bar.done)
|
|
99 |
return
|
|
100 |
}
|
|
101 |
}
|
|
102 |
}
|
|
103 |
|
|
104 |
return bar, serve
|
| 96 | 105 |
}
|
| 97 | 106 |
|
| 98 | 107 |
// ProxyReader wraps r with metrics required for progress tracking.
|
|
| 318 | 327 |
}
|
| 319 | 328 |
}
|
| 320 | 329 |
|
| 321 | |
func (b *Bar) serve(ctx context.Context, s *bState) {
|
| 322 | |
defer b.container.bwg.Done()
|
| 323 | |
for {
|
| 324 | |
select {
|
| 325 | |
case op := <-b.operateState:
|
| 326 | |
op(s)
|
| 327 | |
case <-ctx.Done():
|
| 328 | |
s.decoratorShutdownNotify()
|
| 329 | |
b.cacheState = s
|
| 330 | |
close(b.done)
|
| 331 | |
return
|
| 332 | |
}
|
| 333 | |
}
|
| 334 | |
}
|
| 335 | |
|
| 336 | 330 |
func (b *Bar) render(tw int) {
|
| 337 | 331 |
select {
|
| 338 | 332 |
case b.operateState <- func(s *bState) {
|
|
| 370 | 364 |
}
|
| 371 | 365 |
}
|
| 372 | 366 |
|
| 373 | |
func (b *Bar) subscribeDecorators() {
|
| 374 | |
var averageDecorators []decor.AverageDecorator
|
| 375 | |
var ewmaDecorators []decor.EwmaDecorator
|
| 376 | |
var shutdownListeners []decor.ShutdownListener
|
| 377 | |
b.TraverseDecorators(func(d decor.Decorator) {
|
| 378 | |
if d, ok := d.(decor.AverageDecorator); ok {
|
| 379 | |
averageDecorators = append(averageDecorators, d)
|
| 380 | |
}
|
| 381 | |
if d, ok := d.(decor.EwmaDecorator); ok {
|
| 382 | |
ewmaDecorators = append(ewmaDecorators, d)
|
| 383 | |
}
|
| 384 | |
if d, ok := d.(decor.ShutdownListener); ok {
|
| 385 | |
shutdownListeners = append(shutdownListeners, d)
|
| 386 | |
}
|
| 387 | |
})
|
| 388 | |
b.hasEwmaDecorators = len(ewmaDecorators) != 0
|
| 389 | |
select {
|
| 390 | |
case b.operateState <- func(s *bState) {
|
| 391 | |
s.averageDecorators = averageDecorators
|
| 392 | |
s.ewmaDecorators = ewmaDecorators
|
| 393 | |
s.shutdownListeners = shutdownListeners
|
| 394 | |
}:
|
| 395 | |
case <-b.done:
|
|
367 |
func (b *Bar) subscribeDecorators(bs *bState) {
|
|
368 |
for _, decorators := range [...][]decor.Decorator{
|
|
369 |
bs.pDecorators,
|
|
370 |
bs.aDecorators,
|
|
371 |
} {
|
|
372 |
for _, d := range decorators {
|
|
373 |
d = extractBaseDecorator(d)
|
|
374 |
if d, ok := d.(decor.AverageDecorator); ok {
|
|
375 |
bs.averageDecorators = append(bs.averageDecorators, d)
|
|
376 |
}
|
|
377 |
if d, ok := d.(decor.EwmaDecorator); ok {
|
|
378 |
bs.ewmaDecorators = append(bs.ewmaDecorators, d)
|
|
379 |
}
|
|
380 |
if d, ok := d.(decor.ShutdownListener); ok {
|
|
381 |
bs.shutdownListeners = append(bs.shutdownListeners, d)
|
|
382 |
}
|
|
383 |
}
|
| 396 | 384 |
}
|
| 397 | 385 |
}
|
| 398 | 386 |
|