pool.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // +build linux darwin freebsd netbsd openbsd solaris dragonfly windows
  2. package pb
  3. import (
  4. "sync"
  5. "time"
  6. )
  7. // Create and start new pool with given bars
  8. // You need call pool.Stop() after work
  9. func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) {
  10. pool = new(Pool)
  11. if err = pool.start(); err != nil {
  12. return
  13. }
  14. pool.add(pbs...)
  15. return
  16. }
  17. type Pool struct {
  18. RefreshRate time.Duration
  19. bars []*ProgressBar
  20. quit chan int
  21. finishOnce sync.Once
  22. }
  23. func (p *Pool) add(pbs ...*ProgressBar) {
  24. for _, bar := range pbs {
  25. bar.ManualUpdate = true
  26. bar.NotPrint = true
  27. bar.Start()
  28. p.bars = append(p.bars, bar)
  29. }
  30. }
  31. func (p *Pool) start() (err error) {
  32. p.RefreshRate = DefaultRefreshRate
  33. quit, err := lockEcho()
  34. if err != nil {
  35. return
  36. }
  37. p.quit = make(chan int)
  38. go p.writer(quit)
  39. return
  40. }
  41. func (p *Pool) writer(finish chan int) {
  42. var first = true
  43. for {
  44. select {
  45. case <-time.After(p.RefreshRate):
  46. if p.print(first) {
  47. p.print(false)
  48. finish <- 1
  49. return
  50. }
  51. first = false
  52. case <-p.quit:
  53. finish <- 1
  54. return
  55. }
  56. }
  57. }
  58. // Restore terminal state and close pool
  59. func (p *Pool) Stop() error {
  60. // Wait until one final refresh has passed.
  61. time.Sleep(p.RefreshRate)
  62. p.finishOnce.Do(func() {
  63. close(p.quit)
  64. })
  65. return unlockEcho()
  66. }