Codebase list golang-github-vbauerster-mpb / 0149408
working multi Vladimir Bauer 9 years ago
3 changed file(s) with 92 addition(s) and 90 deletion(s). Raw diff Collapse all Expand all
6767 Alpha float64
6868
6969 incrRequestCh chan *incrRequest
70 incrCh chan int
7071
7172 redrawRequestCh chan *redrawRequest
7273
7879
7980 stopCh chan struct{}
8081 done chan struct{}
81
82 // wg *sync.WaitGroup
8382 }
8483
8584 type Statistics struct {
113112 flushedCh: make(chan struct{}),
114113 stopCh: make(chan struct{}),
115114 done: make(chan struct{}),
115 incrCh: make(chan int),
116116 }
117117 go b.server(wg)
118118 return b
154154
155155 // String returns the string representation of the bar
156156 func (b *Bar) String() string {
157 if b.IsStopped() {
158 return "bar stopped"
159 }
157 // if b.IsStopped() {
158 // return "bar stopped"
159 // }
160160 bufCh := make(chan []byte)
161161 b.redrawRequestCh <- &redrawRequest{bufCh}
162162 return string(<-bufCh)
163163 }
164164
165165 func (b *Bar) flushed() {
166 if !b.IsStopped() {
167 b.flushedCh <- struct{}{}
168 }
169 }
170
171 func (b *Bar) Incr(n int) bool {
172 if b.IsStopped() {
173 return false
174 }
175 result := make(chan bool)
176 b.incrRequestCh <- &incrRequest{n, result}
177 return <-result
166 b.flushedCh <- struct{}{}
167 }
168
169 func (b *Bar) Incr(n int) {
170 // result := make(chan bool)
171 // b.incrRequestCh <- &incrRequest{n, result}
172 // return <-result
173 if !b.IsCompleted() {
174 b.incrCh <- n
175 }
178176 }
179177
180178 func (b *Bar) server(wg *sync.WaitGroup) {
186184 var done bool
187185 for {
188186 select {
189 case r := <-b.incrRequestCh:
190 n := completed + r.amount
191 fmt.Fprintf(os.Stderr, "n = %+v\n", n)
187 case i := <-b.incrCh:
188 n := completed + i
192189 if n > b.total {
193 r.result <- false
194190 completed = b.total
195 fmt.Fprintln(os.Stderr, "n > b.total = return false")
196 break // breaks out of select
197 }
198 // r.result <- true
199 b.updateTimePerItemEstimate(r.amount, blockStartTime)
191 break
192 }
193 b.updateTimePerItemEstimate(i, blockStartTime)
200194 completed = n
195 if completed == b.total && !done {
196 done = true
197 }
201198 blockStartTime = time.Now()
202 if completed == b.total && !done {
203 fmt.Fprintln(os.Stderr, "completed == b.total")
204 done = true
205 wg.Done()
206 }
207 r.result <- true
208199 case d := <-b.decoratorCh:
209200 switch d.kind {
210201 case decoratorAppend:
213204 prependFuncs = append(prependFuncs, d.f)
214205 }
215206 case r := <-b.redrawRequestCh:
216 // fmt.Fprintln(os.Stderr, "redraw")
217207 r.bufCh <- b.draw(buf, completed, appendFuncs, prependFuncs)
218 // case <-b.flushedCh:
219 // if completed == b.total && !done {
220 // fmt.Fprintln(os.Stderr, "wg.Done")
221 // done = true
222 // wg.Done()
223 // } else {
224 // fmt.Fprintln(os.Stderr, "wg.Done not done")
225 // }
208 case <-b.flushedCh:
209 if done && !b.IsCompleted() {
210 fmt.Fprintln(os.Stderr, "flushedCh: wg.Done")
211 close(b.done)
212 wg.Done()
213 }
226214 case <-b.stopCh:
227215 fmt.Fprintln(os.Stderr, "received stop signal")
228 // close(b.incrRequestCh)
229 close(b.done)
230216 if !done {
217 fmt.Fprintln(os.Stderr, "closing done chan: done = false")
218 close(b.done)
231219 done = true
232220 wg.Done()
233221 }
234 // close(b.redrawRequestCh)
235 // close(b.flushedCh)
236222 return
237223 }
238224 }
239225 }
240226
241227 func (b *Bar) Stop() {
242 if !b.IsStopped() {
243 fmt.Fprintln(os.Stderr, "sending to stopCh")
244 b.stopCh <- struct{}{}
245 } else {
246 fmt.Fprintln(os.Stderr, "Stop: already stopped")
247 }
248 }
249
250 func (b *Bar) IsStopped() bool {
228 b.stopCh <- struct{}{}
229 // if !b.IsCompleted() {
230 // fmt.Fprintln(os.Stderr, "sending to stopCh")
231 // } else {
232 // fmt.Fprintln(os.Stderr, "Stop: already stopped")
233 // }
234 }
235
236 func (b *Bar) IsCompleted() bool {
251237 select {
252238 case <-b.done:
253239 return true
00 package main
11
22 import (
3 "sync"
3 "fmt"
4 "math/rand"
5 "runtime"
46 "time"
57
68 "github.com/vbauerster/uiprogress"
79 )
810
11 const (
12 maxBlockSize = 14
13 )
14
915 func main() {
10 waitTime := time.Millisecond * 100
11 // p := uiprogress.New().RefreshInterval(100 * time.Millisecond)
16 runtime.GOMAXPROCS(runtime.NumCPU())
17
18 decor := func(s *uiprogress.Statistics) string {
19 str := fmt.Sprintf("%d/%d", s.Completed, s.Total)
20 return fmt.Sprintf("%-7s", str)
21 }
22
1223 p := uiprogress.New()
1324
14 var wg sync.WaitGroup
15 bar1 := p.AddBar(20).AppendCompleted().PrependElapsed()
16 wg.Add(1)
25 bar1 := p.AddBar(50).AppendETA().PrependFunc(decor)
1726 go func() {
18 defer wg.Done()
19 for bar1.Incr() {
20 time.Sleep(waitTime)
27 blockSize := rand.Intn(maxBlockSize) + 1
28 for i := 0; i < 50; i++ {
29 time.Sleep(time.Duration(blockSize) * (50*time.Millisecond + time.Duration(rand.Intn(5*int(time.Millisecond)))))
30 bar1.Incr(1)
31 blockSize = rand.Intn(maxBlockSize) + 1
2132 }
2233 }()
2334
24 bar2 := p.AddBar(40).AppendCompleted().PrependElapsed()
25 wg.Add(1)
35 bar2 := p.AddBar(100).AppendETA().PrependFunc(decor)
2636 go func() {
27 defer wg.Done()
28 for bar2.Incr() {
29 time.Sleep(waitTime)
37 blockSize := rand.Intn(maxBlockSize) + 1
38 for i := 0; i < 100; i++ {
39 time.Sleep(time.Duration(blockSize) * (50*time.Millisecond + time.Duration(rand.Intn(5*int(time.Millisecond)))))
40 bar2.Incr(1)
41 blockSize = rand.Intn(maxBlockSize) + 1
3042 }
3143 }()
3244
33 time.Sleep(time.Second)
34 bar3 := p.AddBar(80).PrependElapsed().AppendCompleted()
35 wg.Add(1)
45 bar3 := p.AddBar(80).AppendETA().PrependFunc(decor)
3646 go func() {
37 defer wg.Done()
38 for bar3.Incr() {
39 time.Sleep(waitTime)
47 blockSize := rand.Intn(maxBlockSize) + 1
48 for i := 0; i < 80; i++ {
49 time.Sleep(time.Duration(blockSize) * (50*time.Millisecond + time.Duration(rand.Intn(5*int(time.Millisecond)))))
50 bar3.Incr(1)
51 blockSize = rand.Intn(maxBlockSize) + 1
4052 }
4153 }()
4254
43 wg.Wait()
55 // time.Sleep(time.Second)
56 // p.RemoveBar(bar2)
57
4458 p.Stop()
59 fmt.Println("stop")
4560 // p.AddBar(1) // panic: send on closed channnel
4661 }
2626 // Width is the width of the progress bars
2727 // Width int
2828
29 lw *uilive.Writer
29 // lw *uilive.Writer
3030
3131 op chan *operation
3232
4545 // New returns a new progress bar with defaults
4646 func New() *progress {
4747 p := &progress{
48 out: os.Stdout,
49 lw: uilive.New(),
48 out: os.Stdout,
49 // lw: uilive.New(),
5050 op: make(chan *operation),
5151 interval: make(chan time.Duration),
5252 wg: new(sync.WaitGroup),
8484 }
8585
8686 // Bypass returns a writer which allows non-buffered data to be written to the underlying output
87 func (p *progress) Bypass() io.Writer {
88 return p.lw.Bypass()
89 }
87 // func (p *progress) Bypass() io.Writer {
88 // return p.lw.Bypass()
89 // }
9090
9191 // Stop stops listening
9292 func (p *progress) Stop() {
93 fmt.Fprintln(os.Stderr, "p.Stop")
9394 p.wg.Wait()
9495 close(p.op)
9596 }
9798 // server monitors underlying channels and renders any progress bars
9899 func (p *progress) server() {
99100 t := time.NewTicker(refreshRate * time.Millisecond)
100 bars := make([]*Bar, 0)
101 p.lw.Out = p.out
101 bars := make([]*Bar, 0, 4)
102 lw := uilive.New()
103 lw.Out = p.out
102104 for {
103105 select {
104106 case op, ok := <-p.op:
105107 if !ok {
108 fmt.Fprintln(os.Stderr, "Sopping bars")
106109 for _, b := range bars {
107110 b.Stop()
108111 }
109112 t.Stop()
110 p.lw.Stop()
111 // close(p.interval)
112113 return
113114 }
114115 switch op.kind {
128129 }
129130 case <-t.C:
130131 for _, b := range bars {
131 fmt.Fprintln(p.lw, b.String())
132 fmt.Fprintln(lw, b.String())
132133 }
133 p.lw.Flush()
134 // for _, b := range bars {
135 // b.flushed()
136 // }
134 lw.Flush()
135 for _, b := range bars {
136 b.flushed()
137 }
137138 case d := <-p.interval:
138139 t.Stop()
139140 t = time.NewTicker(d)