| 29 | 29 |
bwg *sync.WaitGroup
|
| 30 | 30 |
operateState chan func(*pState)
|
| 31 | 31 |
done chan struct{}
|
| 32 | |
forceRefresh chan time.Time
|
|
32 |
refreshCh chan time.Time
|
| 33 | 33 |
once sync.Once
|
| 34 | 34 |
dlogger *log.Logger
|
| 35 | 35 |
}
|
|
| 48 | 48 |
popCompleted bool
|
| 49 | 49 |
rr time.Duration
|
| 50 | 50 |
uwg *sync.WaitGroup
|
| 51 | |
manualRefresh <-chan time.Time
|
|
51 |
refreshSrc <-chan time.Time
|
| 52 | 52 |
renderDelay <-chan struct{}
|
| 53 | 53 |
shutdownNotifier chan struct{}
|
| 54 | 54 |
parkedBars map[*Bar]*Bar
|
|
| 87 | 87 |
cwg: new(sync.WaitGroup),
|
| 88 | 88 |
bwg: new(sync.WaitGroup),
|
| 89 | 89 |
operateState: make(chan func(*pState)),
|
| 90 | |
forceRefresh: make(chan time.Time),
|
| 91 | 90 |
done: make(chan struct{}),
|
| 92 | 91 |
dlogger: log.New(s.debugOut, "[mpb] ", log.Lshortfile),
|
| 93 | 92 |
}
|
|
| 205 | 204 |
func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
|
| 206 | 205 |
defer p.cwg.Done()
|
| 207 | 206 |
|
| 208 | |
manualOrTickCh, cleanUp := s.manualOrTick()
|
| 209 | |
defer cleanUp()
|
| 210 | |
|
| 211 | |
refreshCh := fanInRefreshSrc(p.done, s.renderDelay, p.forceRefresh, manualOrTickCh)
|
|
207 |
p.refreshCh = s.newTicker(p.done)
|
| 212 | 208 |
|
| 213 | 209 |
for {
|
| 214 | 210 |
select {
|
| 215 | 211 |
case op := <-p.operateState:
|
| 216 | 212 |
op(s)
|
| 217 | |
case _, ok := <-refreshCh:
|
| 218 | |
if !ok {
|
| 219 | |
if s.shutdownNotifier != nil {
|
| 220 | |
close(s.shutdownNotifier)
|
| 221 | |
}
|
| 222 | |
return
|
| 223 | |
}
|
|
213 |
case <-p.refreshCh:
|
| 224 | 214 |
if err := s.render(cw); err != nil {
|
| 225 | |
p.dlogger.Println(err)
|
| 226 | |
}
|
|
215 |
go p.dlogger.Println(err)
|
|
216 |
}
|
|
217 |
case <-s.shutdownNotifier:
|
|
218 |
return
|
| 227 | 219 |
}
|
| 228 | 220 |
}
|
| 229 | 221 |
}
|
|
| 303 | 295 |
return cw.Flush(lineCount)
|
| 304 | 296 |
}
|
| 305 | 297 |
|
| 306 | |
func (s *pState) manualOrTick() (<-chan time.Time, func()) {
|
| 307 | |
if s.manualRefresh != nil {
|
| 308 | |
return s.manualRefresh, func() {}
|
| 309 | |
}
|
| 310 | |
ticker := time.NewTicker(s.rr)
|
| 311 | |
return ticker.C, ticker.Stop
|
|
298 |
func (s *pState) newTicker(done <-chan struct{}) chan time.Time {
|
|
299 |
ch := make(chan time.Time)
|
|
300 |
if s.shutdownNotifier == nil {
|
|
301 |
s.shutdownNotifier = make(chan struct{})
|
|
302 |
}
|
|
303 |
go func() {
|
|
304 |
if s.renderDelay != nil {
|
|
305 |
<-s.renderDelay
|
|
306 |
}
|
|
307 |
if s.refreshSrc == nil {
|
|
308 |
ticker := time.NewTicker(s.rr)
|
|
309 |
defer ticker.Stop()
|
|
310 |
s.refreshSrc = ticker.C
|
|
311 |
}
|
|
312 |
for {
|
|
313 |
select {
|
|
314 |
case tick := <-s.refreshSrc:
|
|
315 |
ch <- tick
|
|
316 |
case <-done:
|
|
317 |
close(s.shutdownNotifier)
|
|
318 |
return
|
|
319 |
}
|
|
320 |
}
|
|
321 |
}()
|
|
322 |
return ch
|
| 312 | 323 |
}
|
| 313 | 324 |
|
| 314 | 325 |
func (s *pState) updateSyncMatrix() {
|
|
| 373 | 384 |
}
|
| 374 | 385 |
}
|
| 375 | 386 |
|
| 376 | |
func fanInRefreshSrc(done, delay <-chan struct{}, channels ...<-chan time.Time) <-chan time.Time {
|
| 377 | |
var wg sync.WaitGroup
|
| 378 | |
multiplexedStream := make(chan time.Time)
|
| 379 | |
start := make(chan struct{})
|
| 380 | |
|
| 381 | |
multiplex := func(c <-chan time.Time) {
|
| 382 | |
defer wg.Done()
|
| 383 | |
<-start
|
| 384 | |
// source channels are never closed (time.Ticker never closes associated
|
| 385 | |
// channel), so we cannot simply range over a c, instead we use select
|
| 386 | |
// inside infinite loop
|
| 387 | |
for {
|
| 388 | |
select {
|
| 389 | |
case v := <-c:
|
| 390 | |
select {
|
| 391 | |
case multiplexedStream <- v:
|
| 392 | |
case <-done:
|
| 393 | |
return
|
| 394 | |
}
|
| 395 | |
case <-done:
|
| 396 | |
return
|
| 397 | |
}
|
| 398 | |
}
|
| 399 | |
}
|
| 400 | |
|
| 401 | |
if delay != nil {
|
| 402 | |
go func() {
|
| 403 | |
<-delay
|
| 404 | |
close(start)
|
| 405 | |
}()
|
| 406 | |
} else {
|
| 407 | |
close(start)
|
| 408 | |
}
|
| 409 | |
|
| 410 | |
wg.Add(len(channels))
|
| 411 | |
for _, c := range channels {
|
| 412 | |
go multiplex(c)
|
| 413 | |
}
|
| 414 | |
|
| 415 | |
go func() {
|
| 416 | |
wg.Wait()
|
| 417 | |
close(multiplexedStream)
|
| 418 | |
}()
|
| 419 | |
|
| 420 | |
return multiplexedStream
|
| 421 | |
}
|
| 422 | |
|
| 423 | 387 |
func extractBaseFiller(f Filler) Filler {
|
| 424 | 388 |
if f, ok := f.(Wrapper); ok {
|
| 425 | 389 |
return extractBaseFiller(f.Base())
|