blob: 69cc825b6c5a731e187b93d9bf968967d54f19f7 [file] [log] [blame]
Abhay Kumara61c5222025-11-10 07:32:50 +00001// +build linux darwin freebsd netbsd openbsd solaris dragonfly windows plan9 aix
2
3package pb
4
5import (
6 "io"
7 "sync"
8 "time"
9
10 "github.com/cheggaaa/pb/v3/termutil"
11)
12
13// Create and start new pool with given bars
14// You need call pool.Stop() after work
15func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) {
16 pool = new(Pool)
17 if err = pool.Start(); err != nil {
18 return
19 }
20 pool.Add(pbs...)
21 return
22}
23
24// NewPool initialises a pool with progress bars, but
25// doesn't start it. You need to call Start manually
26func NewPool(pbs ...*ProgressBar) (pool *Pool) {
27 pool = new(Pool)
28 pool.Add(pbs...)
29 return
30}
31
32type Pool struct {
33 Output io.Writer
34 RefreshRate time.Duration
35 bars []*ProgressBar
36 lastBarsCount int
37 shutdownCh chan struct{}
38 workerCh chan struct{}
39 m sync.Mutex
40 finishOnce sync.Once
41}
42
43// Add progress bars.
44func (p *Pool) Add(pbs ...*ProgressBar) {
45 p.m.Lock()
46 defer p.m.Unlock()
47 for _, bar := range pbs {
48 bar.Set(Static, true)
49 bar.Start()
50 p.bars = append(p.bars, bar)
51 }
52}
53
54func (p *Pool) Start() (err error) {
55 p.RefreshRate = defaultRefreshRate
56 p.shutdownCh, err = termutil.RawModeOn()
57 if err != nil {
58 return
59 }
60 p.workerCh = make(chan struct{})
61 go p.writer()
62 return
63}
64
65func (p *Pool) writer() {
66 var first = true
67 defer func() {
68 if first == false {
69 p.print(false)
70 } else {
71 p.print(true)
72 p.print(false)
73 }
74 close(p.workerCh)
75 }()
76
77 for {
78 select {
79 case <-time.After(p.RefreshRate):
80 if p.print(first) {
81 p.print(false)
82 return
83 }
84 first = false
85 case <-p.shutdownCh:
86 return
87 }
88 }
89}
90
91// Restore terminal state and close pool
92func (p *Pool) Stop() error {
93 p.finishOnce.Do(func() {
94 if p.shutdownCh != nil {
95 close(p.shutdownCh)
96 }
97 })
98
99 // Wait for the worker to complete
100 select {
101 case <-p.workerCh:
102 }
103
104 return termutil.RawModeOff()
105}