Codebase list golang-github-vbauerster-mpb / 2b93f07
refactoring Vladimir Bauer 9 years ago
1 changed file(s) with 52 addition(s) and 75 deletion(s). Raw diff Collapse all Expand all
1515 // after Stop() has been called
1616 var ErrCallAfterStop = errors.New("method call on stopped Progress instance")
1717
18 type opType uint
18 type (
19 // SortType defines sort direction of bar
20 SortType uint
21 opType uint
22
23 operation struct {
24 kind opType
25 bar *Bar
26 result chan bool
27 }
28
29 indexedBarBuffer struct {
30 index int
31 buff []byte
32 }
33
34 indexedBar struct {
35 index int
36 width int
37 bar *Bar
38 }
39 )
1940
2041 const (
2142 opBarAdd opType = iota
2243 opBarRemove
2344 )
24
25 type SortType uint
2645
2746 const (
2847 SortNone SortType = iota
4968 outChangeReqCh chan io.Writer
5069 barCountReqCh chan chan int
5170 done chan struct{}
52 }
53
54 type operation struct {
55 kind opType
56 bar *Bar
57 result chan bool
5871 }
5972
6073 // New creates new Progress instance, which will orchestrate bars rendering
110123 return p
111124 }
112125
113 // func (p *Progress) WithContext(ctx context.Context) *Progress {
114 // if p.BarCount() > 0 {
115 // panic("cannot apply ctx after AddBar has been called")
116 // }
117 // if ctx == nil {
118 // panic("nil context")
119 // }
120 // p.ctx = ctx
121 // return p
122 // }
123
124126 // WithSort sorts the bars, while redering
125127 func (p *Progress) WithSort(sort SortType) *Progress {
126128 p.sort = sort
173175 }
174176 }
175177
178 func (p *Progress) isDone() bool {
179 select {
180 case <-p.done:
181 return true
182 default:
183 return false
184 }
185 }
186
176187 // server monitors underlying channels and renders any progress bars
177188 func (p *Progress) server(cw *cwriter.Writer, t *time.Ticker) {
178 const numDigesters = 4
189 const numDrawers = 4
179190 bars := make([]*Bar, 0, 4)
180191 for {
181192 select {
214225 }
215226
216227 width, _ := cwriter.TerminalWidth()
217 ibars := iBarsGen(p.ctx.Done(), bars, width)
218 c := make(chan *indexedBarBuffer)
228 ibars := iBarsGen(bars, width)
229 c := make(chan indexedBarBuffer)
219230 var wg sync.WaitGroup
220 wg.Add(numDigesters)
221 for i := 0; i < numDigesters; i++ {
231 wg.Add(numDrawers)
232 for i := 0; i < numDrawers; i++ {
222233 go func() {
223 drawer(p.ctx.Done(), ibars, c)
234 drawer(ibars, c)
224235 wg.Done()
225236 }()
226237 }
237248 m[i] = append(m[i], '\n')
238249 cw.Write(m[i])
239250 }
251
240252 cw.Flush()
241 go flushed(p.ctx.Done(), bars)
242
253
254 go func() {
255 for _, b := range bars {
256 b.flushDone()
257 }
258 }()
243259 case d := <-p.rrChangeReqCh:
244260 t.Stop()
245261 t = time.NewTicker(d)
251267 }
252268 }
253269
254 type indexedBarBuffer struct {
255 index int
256 buff []byte
257 }
258
259 type indexedBar struct {
260 index int
261 width int
262 bar *Bar
263 }
264
265 func drawer(done <-chan struct{}, ibars <-chan *indexedBar, c chan<- *indexedBarBuffer) {
270 func drawer(ibars <-chan indexedBar, c chan<- indexedBarBuffer) {
266271 for b := range ibars {
267 select {
268 case c <- &indexedBarBuffer{b.index, b.bar.bytes(b.width)}:
269 case <-done:
270 return
271 }
272 }
273 }
274
275 func iBarsGen(done <-chan struct{}, bars []*Bar, width int) <-chan *indexedBar {
276 ibars := make(chan *indexedBar)
272 c <- indexedBarBuffer{b.index, b.bar.bytes(b.width)}
273 }
274 }
275
276 func iBarsGen(bars []*Bar, width int) <-chan indexedBar {
277 ibars := make(chan indexedBar)
277278 go func() {
278279 defer close(ibars)
279280 for i, b := range bars {
280 select {
281 case ibars <- &indexedBar{i, width, b}:
282 case <-done:
283 return
284 }
281 ibars <- indexedBar{i, width, b}
285282 }
286283 }()
287284 return ibars
288285 }
289
290 func flushed(done <-chan struct{}, bars []*Bar) {
291 for _, b := range bars {
292 select {
293 case <-done:
294 return
295 default:
296 b.flushDone()
297 }
298 }
299 }
300
301 func (p *Progress) isDone() bool {
302 select {
303 case <-p.done:
304 return true
305 default:
306 return false
307 }
308 }