Codebase list golang-github-vbauerster-mpb / cbc336f
Refactoring: pConf to pState, state to bState Vladimir Bauer 8 years ago
8 changed file(s) with 122 addition(s) and 122 deletion(s). Raw diff Collapse all Expand all
3232 quit chan struct{}
3333 // done channel is receiveable after b.server has been quit
3434 done chan struct{}
35 ops chan func(*state)
35 ops chan func(*bState)
3636
3737 // following are used after b.done is receiveable
38 cacheState state
38 cacheState bState
3939
4040 once sync.Once
4141 }
4242
4343 type (
44 state struct {
44 bState struct {
4545 id int
4646 width int
4747 format fmtRunes
7979 total = time.Now().Unix()
8080 }
8181
82 s := state{
82 s := bState{
8383 id: ID,
8484 total: total,
8585 etaAlpha: etaAlpha,
9797 b := &Bar{
9898 quit: make(chan struct{}),
9999 done: make(chan struct{}),
100 ops: make(chan func(*state)),
100 ops: make(chan func(*bState)),
101101 }
102102
103103 go b.server(s, wg, cancel)
107107 // RemoveAllPrependers removes all prepend functions
108108 func (b *Bar) RemoveAllPrependers() {
109109 select {
110 case b.ops <- func(s *state) {
110 case b.ops <- func(s *bState) {
111111 s.prependFuncs = nil
112112 }:
113113 case <-b.quit:
117117 // RemoveAllAppenders removes all append functions
118118 func (b *Bar) RemoveAllAppenders() {
119119 select {
120 case b.ops <- func(s *state) {
120 case b.ops <- func(s *bState) {
121121 s.appendFuncs = nil
122122 }:
123123 case <-b.quit:
140140 return
141141 }
142142 select {
143 case b.ops <- func(s *state) {
143 case b.ops <- func(s *bState) {
144144 next := time.Now()
145145 if s.current == 0 {
146146 s.startTime = next
171171 return
172172 }
173173 select {
174 case b.ops <- func(s *state) {
174 case b.ops <- func(s *bState) {
175175 s.refill = &refill{r, till}
176176 }:
177177 case <-b.quit:
181181 func (b *Bar) NumOfAppenders() int {
182182 result := make(chan int, 1)
183183 select {
184 case b.ops <- func(s *state) { result <- len(s.appendFuncs) }:
184 case b.ops <- func(s *bState) { result <- len(s.appendFuncs) }:
185185 return <-result
186186 case <-b.done:
187187 return len(b.cacheState.appendFuncs)
191191 func (b *Bar) NumOfPrependers() int {
192192 result := make(chan int, 1)
193193 select {
194 case b.ops <- func(s *state) { result <- len(s.prependFuncs) }:
194 case b.ops <- func(s *bState) { result <- len(s.prependFuncs) }:
195195 return <-result
196196 case <-b.done:
197197 return len(b.cacheState.prependFuncs)
202202 func (b *Bar) ID() int {
203203 result := make(chan int, 1)
204204 select {
205 case b.ops <- func(s *state) { result <- s.id }:
205 case b.ops <- func(s *bState) { result <- s.id }:
206206 return <-result
207207 case <-b.done:
208208 return b.cacheState.id
212212 func (b *Bar) Current() int64 {
213213 result := make(chan int64, 1)
214214 select {
215 case b.ops <- func(s *state) { result <- s.current }:
215 case b.ops <- func(s *bState) { result <- s.current }:
216216 return <-result
217217 case <-b.done:
218218 return b.cacheState.current
222222 func (b *Bar) Total() int64 {
223223 result := make(chan int64, 1)
224224 select {
225 case b.ops <- func(s *state) { result <- s.total }:
225 case b.ops <- func(s *bState) { result <- s.total }:
226226 return <-result
227227 case <-b.done:
228228 return b.cacheState.total
234234 // Also you may consider providing your drop ratio via BarDropRatio BarOption func.
235235 func (b *Bar) SetTotal(total int64, final bool) {
236236 select {
237 case b.ops <- func(s *state) {
237 case b.ops <- func(s *bState) {
238238 s.total = total
239239 s.dynamic = !final
240240 }:
265265 close(b.quit)
266266 }
267267
268 func (b *Bar) server(s state, wg *sync.WaitGroup, cancel <-chan struct{}) {
268 func (b *Bar) server(s bState, wg *sync.WaitGroup, cancel <-chan struct{}) {
269269 defer func() {
270270 b.cacheState = s
271271 close(b.done)
291291
292292 go func() {
293293 select {
294 case b.ops <- func(s *state) {
294 case b.ops <- func(s *bState) {
295295 defer func() {
296296 // recovering if external decorators panic
297297 if p := recover(); p != nil {
323323 return ch
324324 }
325325
326 func (s *state) updateTimePerItemEstimate(amount int, now, next time.Time) {
326 func (s *bState) updateTimePerItemEstimate(amount int, now, next time.Time) {
327327 lastBlockTime := now.Sub(s.blockStartTime)
328328 lastItemEstimate := float64(lastBlockTime) / float64(amount)
329329 s.timePerItem = time.Duration((s.etaAlpha * lastItemEstimate) + (1-s.etaAlpha)*float64(s.timePerItem))
330330 s.blockStartTime = next
331331 }
332332
333 func (s *state) draw(termWidth int, prependWs, appendWs *widthSync) {
333 func (s *bState) draw(termWidth int, prependWs, appendWs *widthSync) {
334334 if termWidth <= 0 {
335335 termWidth = s.width
336336 }
373373 s.bufA.WriteByte('\n')
374374 }
375375
376 func (s *state) fillBar(width int) {
376 func (s *bState) fillBar(width int) {
377377 s.bufB.Reset()
378378 s.bufB.WriteRune(s.format[rLeft])
379379 if width <= 2 {
414414 s.bufB.WriteRune(s.format[rRight])
415415 }
416416
417 func newStatistics(s *state) *decor.Statistics {
417 func newStatistics(s *bState) *decor.Statistics {
418418 return &decor.Statistics{
419419 ID: s.id,
420420 Completed: s.completed,
427427 }
428428 }
429429
430 func (s *state) updateFormat(format string) {
430 func (s *bState) updateFormat(format string) {
431431 for i, n := 0, 0; len(format) > 0; i++ {
432432 s.format[i], n = utf8.DecodeRuneInString(format)
433433 format = format[n:]
33
44 // BarOption is a function option which changes the default behavior of a bar,
55 // if passed to p.AddBar(int64, ...BarOption)
6 type BarOption func(*state)
6 type BarOption func(*bState)
77
88 // AppendDecorators let you inject decorators to the bar's right side
99 func AppendDecorators(appenders ...decor.DecoratorFunc) BarOption {
10 return func(bs *state) {
11 bs.appendFuncs = append(bs.appendFuncs, appenders...)
10 return func(s *bState) {
11 s.appendFuncs = append(s.appendFuncs, appenders...)
1212 }
1313 }
1414
1515 // PrependDecorators let you inject decorators to the bar's left side
1616 func PrependDecorators(prependers ...decor.DecoratorFunc) BarOption {
17 return func(bs *state) {
18 bs.prependFuncs = append(bs.prependFuncs, prependers...)
17 return func(s *bState) {
18 s.prependFuncs = append(s.prependFuncs, prependers...)
1919 }
2020 }
2121
2222 // BarTrimLeft trims left side space of the bar
2323 func BarTrimLeft() BarOption {
24 return func(bs *state) {
25 bs.trimLeftSpace = true
24 return func(s *bState) {
25 s.trimLeftSpace = true
2626 }
2727 }
2828
2929 // BarTrimRight trims right space of the bar
3030 func BarTrimRight() BarOption {
31 return func(bs *state) {
32 bs.trimRightSpace = true
31 return func(s *bState) {
32 s.trimRightSpace = true
3333 }
3434 }
3535
3636 // BarTirm trims both left and right spaces of the bar
3737 func BarTrim() BarOption {
38 return func(bs *state) {
39 bs.trimLeftSpace = true
40 bs.trimRightSpace = true
38 return func(s *bState) {
39 s.trimLeftSpace = true
40 s.trimRightSpace = true
4141 }
4242 }
4343
4444 // BarID overwrites internal bar id
4545 func BarID(id int) BarOption {
46 return func(bs *state) {
47 bs.id = id
46 return func(s *bState) {
47 s.id = id
4848 }
4949 }
5050
5252 // You can play with it, if you're not satisfied with default behavior.
5353 // Default value is 0.25.
5454 func BarEtaAlpha(a float64) BarOption {
55 return func(bs *state) {
56 bs.etaAlpha = a
55 return func(s *bState) {
56 s.etaAlpha = a
5757 }
5858 }
5959
6161 // If progress tip reaches total, but total is not final value yet, tip will be
6262 // dropped by specified ratio.
6363 func BarDropRatio(ratio int64) BarOption {
64 return func(bs *state) {
65 bs.dropRatio = ratio
64 return func(s *bState) {
65 s.dropRatio = ratio
6666 }
6767 }
6868
6969 func barWidth(w int) BarOption {
70 return func(bs *state) {
71 bs.width = w
70 return func(s *bState) {
71 s.width = w
7272 }
7373 }
7474
7575 func barFormat(format string) BarOption {
76 return func(bs *state) {
77 bs.updateFormat(format)
76 return func(s *bState) {
77 s.updateFormat(format)
7878 }
7979 }
116116 }
117117 }
118118
119 func newTestState() *state {
120 s := &state{
119 func newTestState() *bState {
120 s := &bState{
121121 trimLeftSpace: true,
122122 trimRightSpace: true,
123123 bufP: new(bytes.Buffer),
1111
1212 // ProgressOption is a function option which changes the default behavior of
1313 // progress pool, if passed to mpb.New(...ProgressOption)
14 type ProgressOption func(*pConf)
14 type ProgressOption func(*pState)
1515
1616 // WithWaitGroup provides means to have a single joint point.
1717 // If *sync.WaitGroup is provided, you can safely call just p.Stop()
1818 // without calling Wait() on provided *sync.WaitGroup.
1919 // Makes sense when there are more than one bar to render.
2020 func WithWaitGroup(wg *sync.WaitGroup) ProgressOption {
21 return func(c *pConf) {
22 c.ewg = wg
21 return func(s *pState) {
22 s.ewg = wg
2323 }
2424 }
2525
2626 // WithWidth overrides default width 80
2727 func WithWidth(w int) ProgressOption {
28 return func(c *pConf) {
28 return func(s *pState) {
2929 if w >= 0 {
30 c.width = w
30 s.width = w
3131 }
3232 }
3333 }
3434
3535 // WithFormat overrides default bar format "[=>-]"
3636 func WithFormat(format string) ProgressOption {
37 return func(c *pConf) {
37 return func(s *pState) {
3838 if utf8.RuneCountInString(format) == formatLen {
39 c.format = format
39 s.format = format
4040 }
4141 }
4242 }
4343
4444 // WithRefreshRate overrides default 100ms refresh rate
4545 func WithRefreshRate(d time.Duration) ProgressOption {
46 return func(c *pConf) {
47 c.ticker.Stop()
48 c.ticker = time.NewTicker(d)
49 c.rr = d
46 return func(s *pState) {
47 s.ticker.Stop()
48 s.ticker = time.NewTicker(d)
49 s.rr = d
5050 }
5151 }
5252
5353 // WithBeforeRenderFunc provided BeforeRender func,
5454 // will be called before each render cycle.
5555 func WithBeforeRenderFunc(f BeforeRender) ProgressOption {
56 return func(c *pConf) {
57 c.beforeRender = f
56 return func(s *pState) {
57 s.beforeRender = f
5858 }
5959 }
6060
6161 // WithCancel provide your cancel channel,
6262 // which you plan to close at some point.
6363 func WithCancel(ch <-chan struct{}) ProgressOption {
64 return func(c *pConf) {
65 c.cancel = ch
64 return func(s *pState) {
65 s.cancel = ch
6666 }
6767 }
6868
6969 // WithShutdownNotifier provided chanel will be closed, inside p.Stop() call
7070 func WithShutdownNotifier(ch chan struct{}) ProgressOption {
71 return func(c *pConf) {
72 c.shutdownNotifier = ch
71 return func(s *pState) {
72 s.shutdownNotifier = ch
7373 }
7474 }
7575
7676 // Output overrides default output os.Stdout
7777 func Output(w io.Writer) ProgressOption {
78 return func(c *pConf) {
78 return func(s *pState) {
7979 if w == nil {
8080 w = ioutil.Discard
8181 }
82 c.cw = cwriter.New(w)
82 s.cw = cwriter.New(w)
8383 }
8484 }
8585
8787 // writer. Could be useful if you want to output something below the bars, while
8888 // they're rendering.
8989 func OutputInterceptors(interseptors ...func(io.Writer)) ProgressOption {
90 return func(c *pConf) {
91 c.interceptors = interseptors
90 return func(s *pState) {
91 s.interceptors = interseptors
9292 }
9393 }
44 import "context"
55
66 func WithContext(ctx context.Context) ProgressOption {
7 return func(c *pConf) {
7 return func(s *pState) {
88 if ctx != nil {
9 c.cancel = ctx.Done()
9 s.cancel = ctx.Done()
1010 }
1111 }
1212 }
1717 Result []chan int
1818 }
1919
20 // progress config, fields are adjustable by user indirectly
21 pConf struct {
20 // progress state, which may contain several bars
21 pState struct {
2222 bars []*Bar
2323
2424 idCounter int
5656 quit chan struct{}
5757 // done channel is receiveable after p.server has been quit
5858 done chan struct{}
59 ops chan func(*pConf)
59 ops chan func(*pState)
6060 }
6161
6262 // New creates new Progress instance, which orchestrates bars rendering process.
6363 // Accepts mpb.ProgressOption funcs for customization.
6464 func New(options ...ProgressOption) *Progress {
6565 // defaults
66 conf := pConf{
66 conf := pState{
6767 bars: make([]*Bar, 0, 3),
6868 width: pwidth,
6969 format: pformat,
8181 ewg: conf.ewg,
8282 wg: new(sync.WaitGroup),
8383 done: make(chan struct{}),
84 ops: make(chan func(*pConf)),
84 ops: make(chan func(*pState)),
8585 quit: make(chan struct{}),
8686 }
8787 go p.server(conf)
9393 p.wg.Add(1)
9494 result := make(chan *Bar, 1)
9595 select {
96 case p.ops <- func(c *pConf) {
96 case p.ops <- func(c *pState) {
9797 options = append(options, barWidth(c.width), barFormat(c.format))
9898 b := newBar(c.idCounter, total, p.wg, c.cancel, options...)
9999 c.bars = append(c.bars, b)
110110 func (p *Progress) RemoveBar(b *Bar) bool {
111111 result := make(chan bool, 1)
112112 select {
113 case p.ops <- func(c *pConf) {
113 case p.ops <- func(c *pState) {
114114 var ok bool
115115 for i, bar := range c.bars {
116116 if bar == b {
132132 func (p *Progress) BarCount() int {
133133 result := make(chan int, 1)
134134 select {
135 case p.ops <- func(c *pConf) {
135 case p.ops <- func(c *pState) {
136136 result <- len(c.bars)
137137 }:
138138 return <-result
207207 return ws
208208 }
209209
210 func (p *pConf) writeAndFlush(tw, numP, numA int) (err error) {
210 func (s *pState) writeAndFlush(tw, numP, numA int) (err error) {
211211 if numP < 0 && numA < 0 {
212212 return
213213 }
214 if p.beforeRender != nil {
215 p.beforeRender(p.bars)
214 if s.beforeRender != nil {
215 s.beforeRender(s.bars)
216216 }
217217
218218 wSyncTimeout := make(chan struct{})
219 time.AfterFunc(p.rr, func() {
219 time.AfterFunc(s.rr, func() {
220220 close(wSyncTimeout)
221221 })
222222
223 prependWs := newWidthSync(wSyncTimeout, len(p.bars), numP)
224 appendWs := newWidthSync(wSyncTimeout, len(p.bars), numA)
225
226 sequence := make([]<-chan *bufReader, len(p.bars))
227 for i, b := range p.bars {
223 prependWs := newWidthSync(wSyncTimeout, len(s.bars), numP)
224 appendWs := newWidthSync(wSyncTimeout, len(s.bars), numA)
225
226 sequence := make([]<-chan *bufReader, len(s.bars))
227 for i, b := range s.bars {
228228 sequence[i] = b.render(tw, prependWs, appendWs)
229229 }
230230
231231 var i int
232232 for r := range fanIn(sequence...) {
233 _, err = p.cw.ReadFrom(r)
233 _, err = s.cw.ReadFrom(r)
234234 defer func(bar *Bar, complete bool) {
235235 if complete {
236236 bar.Complete()
237237 }
238 }(p.bars[i], r.complete)
238 }(s.bars[i], r.complete)
239239 i++
240240 }
241241
242 for _, interceptor := range p.interceptors {
243 interceptor(p.cw)
244 }
245
246 if e := p.cw.Flush(); err == nil {
242 for _, interceptor := range s.interceptors {
243 interceptor(s.cw)
244 }
245
246 if e := s.cw.Flush(); err == nil {
247247 err = e
248248 }
249249 return
1212 "github.com/vbauerster/mpb/cwriter"
1313 )
1414
15 func (p *Progress) server(conf pConf) {
15 func (p *Progress) server(s pState) {
1616 winch := make(chan os.Signal, 1)
1717 signal.Notify(winch, syscall.SIGWINCH)
1818
1919 defer func() {
20 if conf.shutdownNotifier != nil {
21 close(conf.shutdownNotifier)
20 if s.shutdownNotifier != nil {
21 close(s.shutdownNotifier)
2222 }
2323 signal.Stop(winch)
2424 close(p.done)
3333 for {
3434 select {
3535 case op := <-p.ops:
36 op(&conf)
37 case <-conf.ticker.C:
38 if len(conf.bars) == 0 {
36 op(&s)
37 case <-s.ticker.C:
38 if len(s.bars) == 0 {
3939 runtime.Gosched()
4040 break
4141 }
42 b0 := conf.bars[0]
42 b0 := s.bars[0]
4343 if numP == -1 {
4444 numP = b0.NumOfPrependers()
4545 }
4747 numA = b0.NumOfAppenders()
4848 }
4949 tw, _, _ := cwriter.TermSize()
50 err := conf.writeAndFlush(tw, numP, numA)
50 err := s.writeAndFlush(tw, numP, numA)
5151 if err != nil {
5252 fmt.Fprintln(os.Stderr, err)
5353 }
5454 case <-winch:
5555 tw, _, _ := cwriter.TermSize()
56 err := conf.writeAndFlush(tw-tw/8, numP, numA)
56 err := s.writeAndFlush(tw-tw/8, numP, numA)
5757 if err != nil {
5858 fmt.Fprintln(os.Stderr, err)
5959 }
6060 if timer != nil && timer.Reset(resumeDelay) {
6161 break
6262 }
63 conf.ticker.Stop()
63 s.ticker.Stop()
6464 timer = time.NewTimer(resumeDelay)
6565 resumeTicker = timer.C
6666 case <-resumeTicker:
67 conf.ticker = time.NewTicker(conf.rr)
67 s.ticker = time.NewTicker(s.rr)
6868 resumeTicker = nil
69 case <-conf.cancel:
70 conf.ticker.Stop()
71 conf.cancel = nil
69 case <-s.cancel:
70 s.ticker.Stop()
71 s.cancel = nil
7272 case <-p.quit:
73 if conf.cancel != nil {
74 conf.ticker.Stop()
73 if s.cancel != nil {
74 s.ticker.Stop()
7575 }
7676 return
7777 }
99 "github.com/vbauerster/mpb/cwriter"
1010 )
1111
12 func (p *Progress) server(conf pConf) {
12 func (p *Progress) server(s pState) {
1313 defer func() {
14 if conf.shutdownNotifier != nil {
15 close(conf.shutdownNotifier)
14 if s.shutdownNotifier != nil {
15 close(s.shutdownNotifier)
1616 }
1717 close(p.done)
1818 }()
2222 for {
2323 select {
2424 case op := <-p.ops:
25 op(&conf)
26 case <-conf.ticker.C:
27 if len(conf.bars) == 0 {
25 op(&s)
26 case <-s.ticker.C:
27 if len(s.bars) == 0 {
2828 runtime.Gosched()
2929 break
3030 }
31 b0 := conf.bars[0]
31 b0 := s.bars[0]
3232 if numP == -1 {
3333 numP = b0.NumOfPrependers()
3434 }
3636 numA = b0.NumOfAppenders()
3737 }
3838 tw, _, _ := cwriter.TermSize()
39 err := conf.writeAndFlush(tw, numP, numA)
39 err := s.writeAndFlush(tw, numP, numA)
4040 if err != nil {
4141 fmt.Fprintln(os.Stderr, err)
4242 }
43 case <-conf.cancel:
44 conf.ticker.Stop()
45 conf.cancel = nil
43 case <-s.cancel:
44 s.ticker.Stop()
45 s.cancel = nil
4646 case <-p.quit:
47 if conf.cancel != nil {
48 conf.ticker.Stop()
47 if s.cancel != nil {
48 s.ticker.Stop()
4949 }
5050 return
5151 }