Codebase list golang-github-vbauerster-mpb / 4758622
refactoring p.done = ctx.Done() Vladimir Bauer 3 years ago
1 changed file(s) with 38 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
2222
2323 // Progress represents a container that renders one or more progress bars.
2424 type Progress struct {
25 uwg *sync.WaitGroup
26 bwg *sync.WaitGroup
27 operateState chan func(*pState)
28 interceptIO chan func(io.Writer)
29 done, shutdown chan struct{}
30 cancel func()
25 uwg *sync.WaitGroup
26 pwg, bwg sync.WaitGroup
27 operateState chan func(*pState)
28 interceptIO chan func(io.Writer)
29 done <-chan struct{}
30 cancel func()
3131 }
3232
3333 // pState holds bars in its priorityQueue, it gets passed to (*Progress).serve monitor goroutine.
8585 }
8686 }
8787
88 go s.hm.run()
89
90 cw := cwriter.New(s.output)
91 if (cw.IsTerminal() || s.forceAutoRefresh) && !s.manualRefresh {
92 go s.autoRefresh()
93 }
94
8895 p := &Progress{
8996 uwg: s.uwg,
90 bwg: new(sync.WaitGroup),
9197 operateState: make(chan func(*pState)),
9298 interceptIO: make(chan func(io.Writer)),
93 done: make(chan struct{}),
94 shutdown: make(chan struct{}),
99 done: ctx.Done(),
95100 cancel: cancel,
96101 }
97 cw := cwriter.New(s.output)
98 go p.serve(s, cw, s.newTicker(cw.IsTerminal(), p.done))
99 go s.hm.run()
102
103 p.pwg.Add(1)
104 go p.serve(s, cw)
100105 return p
101106 }
102107
226231 // are doing. Proper way to shutdown is to call (*Progress).Wait() instead.
227232 func (p *Progress) Shutdown() {
228233 p.cancel()
229 <-p.shutdown
230 }
231
232 func (p *Progress) serve(s *pState, cw *cwriter.Writer, tickerC <-chan time.Time) {
234 p.pwg.Wait()
235 }
236
237 func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
238 defer p.pwg.Done()
239 render := func() error { return s.render(cw) }
233240 var err error
234 render := func() error { return s.render(cw) }
235241
236242 for {
237243 select {
239245 op(s)
240246 case fn := <-p.interceptIO:
241247 fn(cw)
242 case <-tickerC:
248 case <-s.refreshCh:
243249 e := render()
244250 if e != nil {
245251 p.cancel() // cancel all bars
260266 _, _ = fmt.Fprintln(s.debugOut, err.Error())
261267 }
262268 s.hm.end(s.shutdownNotifier)
263 close(p.shutdown)
264269 return
265270 }
266271 }
267272 }
268273
269 func (s *pState) newTicker(isTerminal bool, done chan struct{}) chan time.Time {
270 ch := make(chan time.Time, 1)
271 go func() {
272 var autoRefresh <-chan time.Time
273 if (isTerminal || s.forceAutoRefresh) && !s.manualRefresh {
274 if s.renderDelay != nil {
275 <-s.renderDelay
276 }
277 ticker := time.NewTicker(s.refreshRate)
278 defer ticker.Stop()
279 autoRefresh = ticker.C
280 }
281 for {
282 select {
283 case t := <-autoRefresh:
284 ch <- t
285 case t := <-s.refreshCh:
286 ch <- t
287 case <-s.ctx.Done():
288 close(done)
289 return
290 }
291 }
292 }()
293 return ch
274 func (s *pState) autoRefresh() {
275 if s.renderDelay != nil {
276 <-s.renderDelay
277 }
278 ticker := time.NewTicker(s.refreshRate)
279 defer ticker.Stop()
280 for {
281 select {
282 case t := <-ticker.C:
283 s.refreshCh <- t
284 case <-s.ctx.Done():
285 return
286 }
287 }
294288 }
295289
296290 func (s *pState) render(cw *cwriter.Writer) (err error) {