Codebase list golang-github-vbauerster-mpb / 3605d1b
avoid data races by waiting inside func(s *bState) This allows ranging over decorators concurrently without using mutexes or other sync book keeping because next call to d.Decor() is awaited. Vladimir Bauer 1 year, 10 months ago
1 changed file(s) with 43 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
158158
159159 // TraverseDecorators traverses all available decorators and calls cb func on each.
160160 func (b *Bar) TraverseDecorators(cb func(decor.Decorator)) {
161 var wg sync.WaitGroup
161162 iter := make(chan decor.Decorator)
162163 select {
163164 case b.operateState <- func(s *bState) {
167168 }
168169 }
169170 close(iter)
171 wg.Wait()
170172 }:
171173 for d := range iter {
172 cb(unwrap(d))
174 d := d
175 go func() {
176 cb(unwrap(d))
177 wg.Done()
178 }()
173179 }
174180 case <-b.ctx.Done():
175181 }
243249 if current < 0 {
244250 return
245251 }
246 result := make(chan *sync.WaitGroup)
252 type item struct {
253 decor.EwmaDecorator
254 n int64
255 }
256 var wg sync.WaitGroup
257 iter := make(chan item)
247258 select {
248259 case b.operateState <- func(s *bState) {
249260 n := current - s.current
261 wg.Add(len(s.ewmaDecorators))
262 for _, d := range s.ewmaDecorators {
263 iter <- item{d, n}
264 }
265 close(iter)
250266 s.current = current
251267 if s.triggerComplete && s.current >= s.total {
252268 s.current = s.total
253269 s.triggerCompletion(b)
254270 }
255 var wg sync.WaitGroup
256 s.decoratorEwmaUpdate(n, iterDur, &wg)
257 result <- &wg
258 }:
259 wg := <-result
260271 wg.Wait()
272 }:
273 for d := range iter {
274 d := d
275 go func() {
276 d.EwmaUpdate(d.n, iterDur)
277 wg.Done()
278 }()
279 }
261280 case <-b.ctx.Done():
262281 }
263282 }
299318 // EwmaIncrInt64 increments progress by amount of n and updates EWMA based
300319 // decorators by dur of a single iteration.
301320 func (b *Bar) EwmaIncrInt64(n int64, iterDur time.Duration) {
302 result := make(chan *sync.WaitGroup)
303 select {
304 case b.operateState <- func(s *bState) {
321 var wg sync.WaitGroup
322 iter := make(chan decor.EwmaDecorator)
323 select {
324 case b.operateState <- func(s *bState) {
325 wg.Add(len(s.ewmaDecorators))
326 for _, d := range s.ewmaDecorators {
327 iter <- d
328 }
329 close(iter)
305330 s.current += n
306331 if s.triggerComplete && s.current >= s.total {
307332 s.current = s.total
308333 s.triggerCompletion(b)
309334 }
310 var wg sync.WaitGroup
311 s.decoratorEwmaUpdate(n, iterDur, &wg)
312 result <- &wg
313 }:
314 wg := <-result
315335 wg.Wait()
336 }:
337 for d := range iter {
338 d := d
339 go func() {
340 d.EwmaUpdate(n, iterDur)
341 wg.Done()
342 }()
343 }
316344 case <-b.ctx.Done():
317345 }
318346 }
573601 return s.triggerComplete && s.current == s.total
574602 }
575603
576 func (s bState) decoratorEwmaUpdate(n int64, dur time.Duration, wg *sync.WaitGroup) {
577 wg.Add(len(s.ewmaDecorators))
578 for _, d := range s.ewmaDecorators {
579 d := d
580 go func() {
581 d.EwmaUpdate(n, dur)
582 wg.Done()
583 }()
584 }
585 }
586
587604 func (s bState) newStatistics(tw int) decor.Statistics {
588605 return decor.Statistics{
589606 AvailableWidth: tw,