iterate subscribed decorators concurrently
Any decorator implemening either of these interfaces, is considered to be subscribed:
- EwmaDecorator
- AverageDecorator
- ShutdownListener
Vladimir Bauer
4 years ago
| 7 | 7 | "log" |
| 8 | 8 | "runtime/debug" |
| 9 | 9 | "strings" |
| 10 | "sync" | |
| 10 | 11 | "time" |
| 11 | 12 | |
| 12 | 13 | "github.com/acarl005/stripansi" |
| 49 | 50 | total int64 |
| 50 | 51 | current int64 |
| 51 | 52 | refill int64 |
| 52 | lastN int64 | |
| 53 | iterated bool | |
| 53 | lastIncrement int64 | |
| 54 | 54 | trimSpace bool |
| 55 | 55 | completed bool |
| 56 | 56 | completeFlushed bool |
| 188 | 188 | func (b *Bar) SetCurrent(current int64) { |
| 189 | 189 | select { |
| 190 | 190 | case b.operateState <- func(s *bState) { |
| 191 | s.iterated = true | |
| 192 | s.lastN = current - s.current | |
| 191 | s.lastIncrement = current - s.current | |
| 193 | 192 | s.current = current |
| 194 | 193 | if s.triggerComplete && s.current >= s.total { |
| 195 | 194 | s.current = s.total |
| 213 | 212 | |
| 214 | 213 | // IncrInt64 increments progress by amount of n. |
| 215 | 214 | func (b *Bar) IncrInt64(n int64) { |
| 216 | select { | |
| 217 | case b.operateState <- func(s *bState) { | |
| 218 | s.iterated = true | |
| 219 | s.lastN = n | |
| 215 | if n <= 0 { | |
| 216 | return | |
| 217 | } | |
| 218 | select { | |
| 219 | case b.operateState <- func(s *bState) { | |
| 220 | s.lastIncrement = n | |
| 220 | 221 | s.current += n |
| 221 | 222 | if s.triggerComplete && s.current >= s.total { |
| 222 | 223 | s.current = s.total |
| 235 | 236 | func (b *Bar) DecoratorEwmaUpdate(dur time.Duration) { |
| 236 | 237 | select { |
| 237 | 238 | case b.operateState <- func(s *bState) { |
| 238 | ewmaIterationUpdate(false, s, dur) | |
| 239 | }: | |
| 240 | case <-b.done: | |
| 241 | ewmaIterationUpdate(true, b.cacheState, dur) | |
| 239 | if s.lastIncrement > 0 { | |
| 240 | s.decoratorEwmaUpdate(dur) | |
| 241 | s.lastIncrement = 0 | |
| 242 | } else { | |
| 243 | panic("increment required before ewma iteration update") | |
| 244 | } | |
| 245 | }: | |
| 246 | case <-b.done: | |
| 247 | if b.cacheState.lastIncrement > 0 { | |
| 248 | b.cacheState.decoratorEwmaUpdate(dur) | |
| 249 | b.cacheState.lastIncrement = 0 | |
| 250 | } | |
| 242 | 251 | } |
| 243 | 252 | } |
| 244 | 253 | |
| 248 | 257 | func (b *Bar) DecoratorAverageAdjust(start time.Time) { |
| 249 | 258 | select { |
| 250 | 259 | case b.operateState <- func(s *bState) { |
| 251 | for _, d := range s.averageDecorators { | |
| 252 | d.AverageAdjust(start) | |
| 253 | } | |
| 260 | s.decoratorAverageAdjust(start) | |
| 254 | 261 | }: |
| 255 | 262 | case <-b.done: |
| 256 | 263 | } |
| 320 | 327 | case op := <-b.operateState: |
| 321 | 328 | op(s) |
| 322 | 329 | case <-ctx.Done(): |
| 323 | // Notifying decorators about shutdown event | |
| 324 | for _, sl := range s.shutdownListeners { | |
| 325 | sl.Shutdown() | |
| 326 | } | |
| 330 | s.decoratorShutdownNotify() | |
| 327 | 331 | b.cacheState = s |
| 328 | 332 | close(b.done) |
| 329 | 333 | return |
| 480 | 484 | return table |
| 481 | 485 | } |
| 482 | 486 | |
| 487 | func (s bState) decoratorEwmaUpdate(dur time.Duration) { | |
| 488 | wg := new(sync.WaitGroup) | |
| 489 | wg.Add(len(s.ewmaDecorators)) | |
| 490 | for _, d := range s.ewmaDecorators { | |
| 491 | d := d | |
| 492 | go func() { | |
| 493 | d.EwmaUpdate(s.lastIncrement, dur) | |
| 494 | wg.Done() | |
| 495 | }() | |
| 496 | } | |
| 497 | wg.Wait() | |
| 498 | } | |
| 499 | ||
| 500 | func (s bState) decoratorAverageAdjust(start time.Time) { | |
| 501 | wg := new(sync.WaitGroup) | |
| 502 | wg.Add(len(s.averageDecorators)) | |
| 503 | for _, d := range s.averageDecorators { | |
| 504 | d := d | |
| 505 | go func() { | |
| 506 | d.AverageAdjust(start) | |
| 507 | wg.Done() | |
| 508 | }() | |
| 509 | } | |
| 510 | wg.Wait() | |
| 511 | } | |
| 512 | ||
| 513 | func (s bState) decoratorShutdownNotify() { | |
| 514 | wg := new(sync.WaitGroup) | |
| 515 | wg.Add(len(s.shutdownListeners)) | |
| 516 | for _, d := range s.shutdownListeners { | |
| 517 | d := d | |
| 518 | go func() { | |
| 519 | d.Shutdown() | |
| 520 | wg.Done() | |
| 521 | }() | |
| 522 | } | |
| 523 | wg.Wait() | |
| 524 | } | |
| 525 | ||
| 483 | 526 | func newStatistics(tw int, s *bState) decor.Statistics { |
| 484 | 527 | return decor.Statistics{ |
| 485 | 528 | ID: s.id, |
| 496 | 539 | return extractBaseDecorator(d.Base()) |
| 497 | 540 | } |
| 498 | 541 | return d |
| 499 | } | |
| 500 | ||
| 501 | func ewmaIterationUpdate(done bool, s *bState, dur time.Duration) { | |
| 502 | if !done && !s.iterated { | |
| 503 | panic("increment required before ewma iteration update") | |
| 504 | } else { | |
| 505 | s.iterated = false | |
| 506 | } | |
| 507 | for _, d := range s.ewmaDecorators { | |
| 508 | d.EwmaUpdate(s.lastN, dur) | |
| 509 | } | |
| 510 | 542 | } |
| 511 | 543 | |
| 512 | 544 | func makePanicExtender(p interface{}) extenderFunc { |