Codebase list golang-github-vbauerster-mpb / f190441
refactoring: bar.Abort Vladimir Bauer 4 years ago
2 changed file(s) with 66 addition(s) and 89 deletion(s). Raw diff Collapse all Expand all
1717 // Bar represents a progress bar.
1818 type Bar struct {
1919 index int // used by heap
20 toShutdown bool
2120 hasEwmaDecorators bool
2221 frameCh chan *frame
2322 operateState chan func(*bState)
6261 }
6362
6463 type frame struct {
65 reader io.Reader
66 lines int
64 reader io.Reader
65 lines int
66 shutdown bool
67 abort bool
6768 }
6869
6970 func newBar(container *Progress, bs *bState) (*Bar, func()) {
274275 // if bar is already in complete state. If drop is true bar will be
275276 // removed as well.
276277 func (b *Bar) Abort(drop bool) {
277 done := make(chan struct{})
278 select {
279 case b.operateState <- func(s *bState) {
280 if s.completed {
281 close(done)
278 select {
279 case b.operateState <- func(s *bState) {
280 if s.completed || s.aborted {
282281 return
283282 }
284283 s.aborted = true
285 b.cancel()
286 // container must be run during lifetime of this inner goroutine
287 // we control this by done channel declared above
288 go func() {
289 if drop {
290 b.container.dropBar(b)
291 } else {
292 var anyOtherUncompleted bool
293 b.container.traverseBars(func(bar *Bar) bool {
294 anyOtherUncompleted = b != bar && !bar.Completed()
295 return !anyOtherUncompleted
296 })
297 if !anyOtherUncompleted {
298 b.container.refreshCh <- time.Now()
299 }
300 }
301 close(done) // release hold of Abort
302 }()
303 }:
304 // guarantee: container is alive during lifetime of this hold
305 <-done
284 s.dropOnComplete = drop
285 go b.forceRefreshIfLastUncompleted()
286 }:
287 <-b.done
306288 case <-b.done:
307289 }
308290 }
321303 func (b *Bar) render(tw int) {
322304 select {
323305 case b.operateState <- func(s *bState) {
306 var reader io.Reader
307 var lines int
324308 stat := newStatistics(tw, s)
325309 defer func() {
326310 // recovering if user defined decorator panics for example
327311 if p := recover(); p != nil {
328 if b.recoveredPanic == nil {
329 if s.debugOut != nil {
330 fmt.Fprintln(s.debugOut, p)
331 _, _ = s.debugOut.Write(debug.Stack())
332 }
333 s.extender = makePanicExtender(p)
334 b.toShutdown = !b.toShutdown
335 b.recoveredPanic = p
312 if s.debugOut != nil {
313 fmt.Fprintln(s.debugOut, p)
314 _, _ = s.debugOut.Write(debug.Stack())
336315 }
337 reader, lines := s.extender(nil, s.reqWidth, stat)
338 b.frameCh <- &frame{reader, lines + 1}
339 }
340 s.completeFlushed = s.completed
316 s.aborted = true
317 s.extender = makePanicExtender(p)
318 reader, lines = s.extender(nil, s.reqWidth, stat)
319 b.recoveredPanic = p
320 }
321 b.frameCh <- &frame{
322 reader: reader,
323 lines: lines + 1,
324 shutdown: s.completed && !s.completeFlushed,
325 abort: s.aborted && !s.completeFlushed,
326 }
327 s.completeFlushed = s.completed || s.aborted
341328 }()
342 reader, lines := s.extender(s.draw(stat), s.reqWidth, stat)
343 b.toShutdown = s.completed && !s.completeFlushed
344 b.frameCh <- &frame{reader, lines + 1}
345 }:
346 case <-b.done:
347 s := b.bs
348 stat := newStatistics(tw, s)
349 var r io.Reader
350329 if b.recoveredPanic == nil {
351 r = s.draw(stat)
352 }
353 reader, lines := s.extender(r, s.reqWidth, stat)
354 b.frameCh <- &frame{reader, lines + 1}
330 reader = s.draw(stat)
331 }
332 reader, lines = s.extender(reader, s.reqWidth, stat)
333 }:
334 case <-b.done:
335 var reader io.Reader
336 var lines int
337 stat, s := newStatistics(tw, b.bs), b.bs
338 if b.recoveredPanic == nil {
339 reader = s.draw(stat)
340 }
341 reader, lines = s.extender(reader, s.reqWidth, stat)
342 b.frameCh <- &frame{
343 reader: reader,
344 lines: lines + 1,
345 }
355346 }
356347 }
357348
521512 Total: s.total,
522513 Current: s.current,
523514 Refill: s.refill,
524 Completed: s.completeFlushed,
515 Completed: s.completeFlushed && !s.aborted,
525516 Aborted: s.aborted,
526517 }
527518 }
1515 )
1616
1717 const (
18 // default RefreshRate
19 prr = 150 * time.Millisecond
18 prr = 150 * time.Millisecond // default RefreshRate
2019 )
2120
2221 // Progress represents a container that renders one or more progress bars.
139138 case <-p.done:
140139 p.bwg.Done()
141140 panic(fmt.Sprintf("%T instance can't be reused after it's done!", p))
142 }
143 }
144
145 func (p *Progress) dropBar(b *Bar) {
146 select {
147 case p.operateState <- func(s *pState) {
148 if b.index < 0 {
149 return
150 }
151 heap.Remove(&s.bHeap, b.index)
152 s.heapUpdated = true
153 }:
154 case <-p.done:
155141 }
156142 }
157143
317303
318304 func (s *pState) flush(cw *cwriter.Writer) error {
319305 var totalLines int
320 bm := make(map[*Bar]int, s.bHeap.Len())
306 bm := make(map[*Bar]*frame, s.bHeap.Len())
321307 for s.bHeap.Len() > 0 {
322308 b := heap.Pop(&s.bHeap).(*Bar)
323309 frame := <-b.frameCh
325311 if err != nil {
326312 return err
327313 }
328 if b.toShutdown {
329 if b.recoveredPanic != nil {
314 if frame.abort {
315 s.barShutdownQueue = append(s.barShutdownQueue, b)
316 } else if frame.shutdown {
317 // shutdown at next flush
318 // this ensures no bar ends up with less than 100% rendered
319 defer func() {
330320 s.barShutdownQueue = append(s.barShutdownQueue, b)
331 b.toShutdown = false
332 } else {
333 // shutdown at next flush
334 // this ensures no bar ends up with less than 100% rendered
335 defer func() {
336 s.barShutdownQueue = append(s.barShutdownQueue, b)
337 }()
338 }
339 }
340 bm[b] = frame.lines
321 }()
322 }
341323 totalLines += frame.lines
324 bm[b] = frame
342325 }
343326
344327 for _, b := range s.barShutdownQueue {
328 b.cancel()
329 <-b.done // waiting for b.done, so it's safe to read b.bs
330 var toDrop bool
345331 if qb, ok := s.queueBars[b]; ok {
332 delete(s.queueBars, b)
346333 qb.bar.bs.priority = b.bs.priority
347334 heap.Push(&s.bHeap, qb.bar)
348 delete(s.queueBars, b)
349 b.bs.dropOnComplete = true
350335 go qb.serve()
336 toDrop = true
351337 } else if s.popCompleted && !b.bs.noPop {
352 totalLines -= bm[b]
353 b.bs.dropOnComplete = true
354 }
355 if b.bs.dropOnComplete {
338 frame := bm[b]
339 totalLines -= frame.lines
340 toDrop = true
341 }
342 if toDrop || b.bs.dropOnComplete {
356343 delete(bm, b)
357344 s.heapUpdated = true
358345 }
359 b.cancel()
360346 }
361347 s.barShutdownQueue = s.barShutdownQueue[0:0]
362348