| // +build linux darwin freebsd netbsd openbsd solaris dragonfly windows |
| |
| package pb |
| |
| import ( |
| "io" |
| "sync" |
| "time" |
| ) |
| |
| // Create and start new pool with given bars |
| // You need call pool.Stop() after work |
| func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) { |
| pool = new(Pool) |
| if err = pool.start(); err != nil { |
| return |
| } |
| pool.Add(pbs...) |
| return |
| } |
| |
| type Pool struct { |
| Output io.Writer |
| RefreshRate time.Duration |
| bars []*ProgressBar |
| lastBarsCount int |
| quit chan int |
| m sync.Mutex |
| finishOnce sync.Once |
| } |
| |
| // Add progress bars. |
| func (p *Pool) Add(pbs ...*ProgressBar) { |
| p.m.Lock() |
| defer p.m.Unlock() |
| for _, bar := range pbs { |
| bar.ManualUpdate = true |
| bar.NotPrint = true |
| bar.Start() |
| p.bars = append(p.bars, bar) |
| } |
| } |
| |
| func (p *Pool) start() (err error) { |
| p.RefreshRate = DefaultRefreshRate |
| quit, err := lockEcho() |
| if err != nil { |
| return |
| } |
| p.quit = make(chan int) |
| go p.writer(quit) |
| return |
| } |
| |
| func (p *Pool) writer(finish chan int) { |
| var first = true |
| for { |
| select { |
| case <-time.After(p.RefreshRate): |
| if p.print(first) { |
| p.print(false) |
| finish <- 1 |
| return |
| } |
| first = false |
| case <-p.quit: |
| finish <- 1 |
| return |
| } |
| } |
| } |
| |
| // Restore terminal state and close pool |
| func (p *Pool) Stop() error { |
| // Wait until one final refresh has passed. |
| time.Sleep(p.RefreshRate) |
| |
| p.finishOnce.Do(func() { |
| close(p.quit) |
| }) |
| return unlockEcho() |
| } |