Codebase list golang-github-vbauerster-mpb / d449d0f
IsStopped Vladimir Bauer 9 years ago
2 changed file(s) with 83 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
11
22 import (
33 "fmt"
4 "os"
45 "sync"
56 "time"
67 )
7374
7475 timePerItemEstimate time.Duration
7576
76 flushedCh chan *sync.WaitGroup
77 flushedCh chan struct{}
78
79 stopCh chan struct{}
80 done chan struct{}
81
82 // wg *sync.WaitGroup
7783 }
7884
7985 type Statistics struct {
9197 }
9298
9399 // NewBar returns a new progress bar
94 func newBar(total int) *Bar {
100 func newBar(total int, wg *sync.WaitGroup) *Bar {
95101 b := &Bar{
96102 Alpha: 0.25,
97103 total: total,
104110 incrRequestCh: make(chan *incrRequest),
105111 redrawRequestCh: make(chan *redrawRequest),
106112 decoratorCh: make(chan *decorator),
107 flushedCh: make(chan *sync.WaitGroup),
108 }
109 go b.server()
113 flushedCh: make(chan struct{}),
114 stopCh: make(chan struct{}),
115 done: make(chan struct{}),
116 }
117 go b.server(wg)
110118 return b
111119 }
112120
146154
147155 // String returns the string representation of the bar
148156 func (b *Bar) String() string {
157 if b.IsStopped() {
158 return "bar stopped"
159 }
149160 bufCh := make(chan []byte)
150161 b.redrawRequestCh <- &redrawRequest{bufCh}
151162 return string(<-bufCh)
152163 }
153164
154 // func (b *Bar) bytes() []byte {
155 // bufch := make(chan []byte)
156 // b.redrawRequestCh <- &redrawRequest{bufch}
157 // return <-bufch
158 // }
159
160 func (b *Bar) flushed(wg *sync.WaitGroup) {
161 b.flushedCh <- wg
165 func (b *Bar) flushed() {
166 if !b.IsStopped() {
167 b.flushedCh <- struct{}{}
168 }
162169 }
163170
164171 func (b *Bar) Incr(n int) bool {
172 if b.IsStopped() {
173 return false
174 }
165175 result := make(chan bool)
166176 b.incrRequestCh <- &incrRequest{n, result}
167177 return <-result
168178 }
169179
170 func (b *Bar) server() {
180 func (b *Bar) server(wg *sync.WaitGroup) {
171181 var completed int
172182 blockStartTime := time.Now()
173183 buf := make([]byte, b.Width, b.Width+24)
174184 var appendFuncs []DecoratorFunc
175185 var prependFuncs []DecoratorFunc
186 var done bool
176187 for {
177188 select {
178189 case r := <-b.incrRequestCh:
179190 n := completed + r.amount
191 fmt.Fprintf(os.Stderr, "n = %+v\n", n)
180192 if n > b.total {
193 r.result <- false
181194 completed = b.total
182 r.result <- false
183 break // breaks out of select, not for
184 }
195 fmt.Fprintln(os.Stderr, "n > b.total = return false")
196 break // breaks out of select
197 }
198 // r.result <- true
185199 b.updateTimePerItemEstimate(r.amount, blockStartTime)
186200 completed = n
187201 blockStartTime = time.Now()
202 if completed == b.total && !done {
203 fmt.Fprintln(os.Stderr, "completed == b.total")
204 done = true
205 wg.Done()
206 }
188207 r.result <- true
189208 case d := <-b.decoratorCh:
190209 switch d.kind {
194213 prependFuncs = append(prependFuncs, d.f)
195214 }
196215 case r := <-b.redrawRequestCh:
216 // fmt.Fprintln(os.Stderr, "redraw")
197217 r.bufCh <- b.draw(buf, completed, appendFuncs, prependFuncs)
198 case wg := <-b.flushedCh:
199 if completed == b.total {
200 close(b.incrRequestCh)
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 // }
226 case <-b.stopCh:
227 fmt.Fprintln(os.Stderr, "received stop signal")
228 // close(b.incrRequestCh)
229 close(b.done)
230 if !done {
231 done = true
201232 wg.Done()
202 return
203 }
233 }
234 // close(b.redrawRequestCh)
235 // close(b.flushedCh)
236 return
204237 }
238 }
239 }
240
241 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 {
251 select {
252 case <-b.done:
253 return true
254 default:
255 return false
205256 }
206257 }
207258
1616 barRemove
1717 )
1818
19 const refreshRate = 50
19 const refreshRate = 60
2020
2121 // progress represents the container that renders progress bars
2222 type progress struct {
5858 // AddBar creates a new progress bar and adds to the container
5959 func (p *progress) AddBar(total int) *Bar {
6060 p.wg.Add(1)
61 bar := newBar(total)
61 bar := newBar(total, p.wg)
6262 // bar.Width = p.Width
6363 p.op <- &operation{barAdd, bar, nil}
6464 return bar
103103 select {
104104 case op, ok := <-p.op:
105105 if !ok {
106 for _, b := range bars {
107 b.Stop()
108 }
106109 t.Stop()
107 close(p.interval)
108110 p.lw.Stop()
111 // close(p.interval)
109112 return
110113 }
111114 switch op.kind {
117120 if b == op.bar {
118121 bars = append(bars[:i], bars[i+1:]...)
119122 ok = true
123 b.Stop()
120124 break
121125 }
122126 }
127131 fmt.Fprintln(p.lw, b.String())
128132 }
129133 p.lw.Flush()
130 for _, b := range bars {
131 b.flushed(p.wg)
132 }
134 // for _, b := range bars {
135 // b.flushed()
136 // }
133137 case d := <-p.interval:
134138 t.Stop()
135139 t = time.NewTicker(d)