Improved perf of bar.Completed method
Vladimir Bauer
7 years ago
| 20 | 20 | rRight |
| 21 | 21 | ) |
| 22 | 22 | |
| 23 | const ( | |
| 24 | cmdId = 1 << iota | |
| 25 | cmdCurrent | |
| 26 | cmdCompleted | |
| 27 | ) | |
| 28 | ||
| 29 | 23 | const formatLen = 5 |
| 30 | 24 | |
| 31 | 25 | type barRunes [formatLen]rune |
| 38 | 32 | runningBar *Bar |
| 39 | 33 | cacheState *bState |
| 40 | 34 | operateState chan func(*bState) |
| 41 | cmdValue chan int | |
| 35 | int64Ch chan int64 | |
| 36 | boolCh chan bool | |
| 42 | 37 | frameReaderCh chan io.Reader |
| 43 | 38 | syncTableCh chan [][]chan int |
| 44 | 39 | bufNL *bytes.Buffer |
| 111 | 106 | priority: s.priority, |
| 112 | 107 | runningBar: s.runningBar, |
| 113 | 108 | operateState: make(chan func(*bState)), |
| 114 | cmdValue: make(chan int), | |
| 109 | int64Ch: make(chan int64), | |
| 110 | boolCh: make(chan bool), | |
| 115 | 111 | frameReaderCh: make(chan io.Reader, 1), |
| 116 | 112 | syncTableCh: make(chan [][]chan int), |
| 117 | 113 | done: make(chan struct{}), |
| 158 | 154 | // ID returs id of the bar. |
| 159 | 155 | func (b *Bar) ID() int { |
| 160 | 156 | select { |
| 161 | case b.cmdValue <- cmdId: | |
| 162 | return <-b.cmdValue | |
| 157 | case b.operateState <- func(s *bState) { b.int64Ch <- int64(s.id) }: | |
| 158 | return int(<-b.int64Ch) | |
| 163 | 159 | case <-b.done: |
| 164 | 160 | return b.cacheState.id |
| 165 | 161 | } |
| 168 | 164 | // Current returns bar's current number, in other words sum of all increments. |
| 169 | 165 | func (b *Bar) Current() int64 { |
| 170 | 166 | select { |
| 171 | case b.cmdValue <- cmdCurrent: | |
| 172 | return int64(<-b.cmdValue) | |
| 167 | case b.operateState <- func(s *bState) { b.int64Ch <- s.current }: | |
| 168 | return <-b.int64Ch | |
| 173 | 169 | case <-b.done: |
| 174 | 170 | return b.cacheState.current |
| 175 | 171 | } |
| 223 | 219 | |
| 224 | 220 | // Completed reports whether the bar is in completed state. |
| 225 | 221 | func (b *Bar) Completed() bool { |
| 226 | b.cmdValue <- cmdCompleted | |
| 227 | if v := <-b.cmdValue; v == 1 { | |
| 228 | return true | |
| 229 | } | |
| 230 | return false | |
| 222 | // omit select here, because primary usage of the method is for loop | |
| 223 | // condition, like for !bar.Completed() {...} | |
| 224 | // so when toComplete=true it is called once (at which time, the bar is still alive), | |
| 225 | // then quits the loop and never suppose to be called afterwards. | |
| 226 | return <-b.boolCh | |
| 231 | 227 | } |
| 232 | 228 | |
| 233 | 229 | func (b *Bar) wSyncTable() [][]chan int { |
| 245 | 241 | select { |
| 246 | 242 | case op := <-b.operateState: |
| 247 | 243 | op(s) |
| 248 | case cmd := <-b.cmdValue: | |
| 249 | switch { | |
| 250 | case (cmd & cmdId) != 0: | |
| 251 | b.cmdValue <- s.id | |
| 252 | case (cmd & cmdCurrent) != 0: | |
| 253 | b.cmdValue <- int(s.current) | |
| 254 | case (cmd & cmdCompleted) != 0: | |
| 255 | var v int | |
| 256 | if s.toComplete { | |
| 257 | v = 1 | |
| 258 | } | |
| 259 | b.cmdValue <- v | |
| 260 | } | |
| 244 | case b.boolCh <- s.toComplete: | |
| 261 | 245 | case <-cancel: |
| 262 | 246 | s.toComplete = true |
| 263 | 247 | cancel = nil |