Request totalUnknownBarStopReqCh before stop
Vladimir Bauer
9 years ago
| 3 | 3 | "fmt" |
| 4 | 4 | "io" |
| 5 | 5 | "os" |
| 6 | "runtime" | |
| 7 | 6 | "sync" |
| 8 | 7 | "time" |
| 9 | 8 | "unicode/utf8" |
| 62 | 61 | // WaitGroup for internal rendering sync |
| 63 | 62 | wg *sync.WaitGroup |
| 64 | 63 | |
| 65 | done chan struct{} | |
| 66 | userConfCh chan userConf | |
| 67 | bCommandCh chan *bCommandData | |
| 68 | barCountCh chan int | |
| 69 | stopReqCh chan struct{} | |
| 64 | done chan struct{} | |
| 65 | userConfCh chan userConf | |
| 66 | bCommandCh chan *bCommandData | |
| 67 | barCountCh chan int | |
| 68 | stopReqCh chan struct{} | |
| 69 | totalUnknownBarStopReqCh chan struct{} | |
| 70 | 70 | |
| 71 | 71 | // follawing is used after (*Progress.done) is closed |
| 72 | 72 | conf userConf |
| 77 | 77 | // If you don't plan to cancel, it is safe to feed with nil |
| 78 | 78 | func New() *Progress { |
| 79 | 79 | p := &Progress{ |
| 80 | wg: new(sync.WaitGroup), | |
| 81 | done: make(chan struct{}), | |
| 82 | userConfCh: make(chan userConf), | |
| 83 | bCommandCh: make(chan *bCommandData), | |
| 84 | barCountCh: make(chan int), | |
| 85 | stopReqCh: make(chan struct{}), | |
| 80 | wg: new(sync.WaitGroup), | |
| 81 | done: make(chan struct{}), | |
| 82 | userConfCh: make(chan userConf), | |
| 83 | bCommandCh: make(chan *bCommandData), | |
| 84 | barCountCh: make(chan int), | |
| 85 | stopReqCh: make(chan struct{}), | |
| 86 | totalUnknownBarStopReqCh: make(chan struct{}), | |
| 86 | 87 | } |
| 87 | 88 | go p.server(userConf{ |
| 88 | 89 | width: pwidth, |
| 211 | 212 | case <-p.done: |
| 212 | 213 | return |
| 213 | 214 | default: |
| 214 | p.wg.Wait() // wait for all bars to quit | |
| 215 | // complet Total unknown bars | |
| 216 | p.totalUnknownBarStopReqCh <- struct{}{} | |
| 217 | // wait for all bars to quit | |
| 218 | p.wg.Wait() | |
| 219 | // stop request | |
| 215 | 220 | p.stopReqCh <- struct{}{} |
| 216 | <-p.done // wait for p.server to quit | |
| 221 | // wait for p.server to quit | |
| 222 | <-p.done | |
| 217 | 223 | } |
| 218 | 224 | } |
| 219 | 225 | |
| 240 | 246 | func (p *Progress) server(conf userConf) { |
| 241 | 247 | |
| 242 | 248 | defer func() { |
| 249 | conf.ticker.Stop() | |
| 250 | conf.cw.Flush() | |
| 243 | 251 | p.conf = conf |
| 244 | conf.ticker.Stop() | |
| 245 | 252 | if conf.shutdownNotifier != nil { |
| 246 | 253 | close(conf.shutdownNotifier) |
| 247 | 254 | } |
| 250 | 257 | |
| 251 | 258 | recoverFn := func(ch chan []byte) { |
| 252 | 259 | if p := recover(); p != nil { |
| 253 | var buf [4096]byte | |
| 254 | n := runtime.Stack(buf[:], false) | |
| 255 | os.Stderr.Write(buf[:n]) | |
| 256 | 260 | ch <- []byte(fmt.Sprintln(p)) |
| 257 | 261 | } |
| 258 | 262 | close(ch) |
| 328 | 332 | for _, b := range bars { |
| 329 | 333 | b.flushed() |
| 330 | 334 | } |
| 331 | case <-p.stopReqCh: | |
| 335 | case <-p.totalUnknownBarStopReqCh: | |
| 332 | 336 | for _, b := range bars { |
| 333 | 337 | if b.GetStatistics().Total <= 0 { |
| 334 | 338 | b.Completed() |
| 335 | 339 | } |
| 336 | 340 | } |
| 341 | case <-p.stopReqCh: | |
| 337 | 342 | return |
| 338 | 343 | } |
| 339 | 344 | } |