make dropS, dropD channels on pState
Those channels closed once on unrecoverable errors
in order to prevent goroutine leaks.
Vladimir Bauer
3 years ago
| 181 | 181 |
}
|
| 182 | 182 |
|
| 183 | 183 |
for _, columnCase := range testCases {
|
| 184 | |
mpb.SyncWidth(toSyncMatrix(columnCase))
|
|
184 |
mpb.SyncWidth(toSyncMatrix(columnCase), nil)
|
| 185 | 185 |
var results []chan string
|
| 186 | 186 |
for _, step := range columnCase {
|
| 187 | 187 |
step := step
|
| 64 | 64 |
sync = false
|
| 65 | 65 |
l = bHeap.Len()
|
| 66 | 66 |
}
|
| 67 | |
syncWidth(pMatrix)
|
| 68 | |
syncWidth(aMatrix)
|
|
67 |
drop := req.data.(<-chan struct{})
|
|
68 |
syncWidth(pMatrix, drop)
|
|
69 |
syncWidth(aMatrix, drop)
|
| 69 | 70 |
case h_iter:
|
| 70 | 71 |
data := req.data.(iterData)
|
| 71 | 72 |
for _, b := range bHeap {
|
|
| 103 | 104 |
}
|
| 104 | 105 |
}
|
| 105 | 106 |
|
| 106 | |
func (m heapManager) sync() {
|
| 107 | |
m <- heapRequest{cmd: h_sync}
|
|
107 |
func (m heapManager) sync(drop <-chan struct{}) {
|
|
108 |
m <- heapRequest{cmd: h_sync, data: drop}
|
| 108 | 109 |
}
|
| 109 | 110 |
|
| 110 | 111 |
func (m heapManager) push(b *Bar, sync bool) {
|
|
| 134 | 135 |
m <- heapRequest{cmd: h_end, data: ch}
|
| 135 | 136 |
}
|
| 136 | 137 |
|
| 137 | |
func syncWidth(matrix map[int][]chan int) {
|
|
138 |
func syncWidth(matrix map[int][]chan int, drop <-chan struct{}) {
|
| 138 | 139 |
for _, column := range matrix {
|
| 139 | |
go maxWidthDistributor(column)
|
|
140 |
go maxWidthDistributor(column, drop)
|
| 140 | 141 |
}
|
| 141 | 142 |
}
|
| 142 | 143 |
|
| 143 | |
func maxWidthDistributor(column []chan int) {
|
|
144 |
func maxWidthDistributor(column []chan int, drop <-chan struct{}) {
|
| 144 | 145 |
var maxWidth int
|
| 145 | 146 |
for _, ch := range column {
|
| 146 | |
if w := <-ch; w > maxWidth {
|
| 147 | |
maxWidth = w
|
|
147 |
select {
|
|
148 |
case w := <-ch:
|
|
149 |
if w > maxWidth {
|
|
150 |
maxWidth = w
|
|
151 |
}
|
|
152 |
case <-drop:
|
|
153 |
return
|
| 148 | 154 |
}
|
| 149 | 155 |
}
|
| 150 | 156 |
for _, ch := range column {
|
| 33 | 33 |
|
| 34 | 34 |
// pState holds bars in its priorityQueue, it gets passed to (*Progress).serve monitor goroutine.
|
| 35 | 35 |
type pState struct {
|
| 36 | |
ctx context.Context
|
| 37 | |
hm heapManager
|
| 38 | |
rows []io.Reader
|
|
36 |
ctx context.Context
|
|
37 |
hm heapManager
|
|
38 |
dropS, dropD chan struct{}
|
|
39 |
rows []io.Reader
|
| 39 | 40 |
|
| 40 | 41 |
// following are provided/overrided by user
|
| 41 | 42 |
refreshRate time.Duration
|
|
| 68 | 69 |
s := &pState{
|
| 69 | 70 |
ctx: ctx,
|
| 70 | 71 |
hm: make(heapManager),
|
|
72 |
dropS: make(chan struct{}),
|
|
73 |
dropD: make(chan struct{}),
|
| 71 | 74 |
rows: make([]io.Reader, 32),
|
| 72 | 75 |
refreshRate: defaultRefreshRate,
|
| 73 | 76 |
popPriority: math.MinInt32,
|
|
| 299 | 302 |
}
|
| 300 | 303 |
|
| 301 | 304 |
func (s *pState) render(cw *cwriter.Writer) (err error) {
|
|
305 |
s.hm.sync(s.dropS)
|
|
306 |
|
| 302 | 307 |
var width, height int
|
| 303 | 308 |
if cw.IsTerminal() {
|
| 304 | 309 |
width, height, err = cw.GetTermSize()
|
| 305 | 310 |
if err != nil {
|
|
311 |
close(s.dropS)
|
| 306 | 312 |
return err
|
| 307 | 313 |
}
|
| 308 | 314 |
} else {
|
|
| 314 | 320 |
height = 100
|
| 315 | 321 |
}
|
| 316 | 322 |
|
| 317 | |
s.hm.sync()
|
| 318 | 323 |
iter := make(chan *Bar)
|
| 319 | 324 |
s.hm.iter(iter, nil)
|
| 320 | 325 |
for b := range iter {
|
|
| 330 | 335 |
|
| 331 | 336 |
var popCount int
|
| 332 | 337 |
|
| 333 | |
iter, drop := make(chan *Bar), make(chan struct{})
|
| 334 | |
s.hm.drain(iter, drop)
|
|
338 |
iter := make(chan *Bar)
|
|
339 |
s.hm.drain(iter, s.dropD)
|
| 335 | 340 |
s.rows = s.rows[:0]
|
| 336 | 341 |
|
| 337 | 342 |
for b := range iter {
|
| 338 | 343 |
frame := <-b.frameCh
|
| 339 | 344 |
if frame.err != nil {
|
| 340 | |
close(drop)
|
|
345 |
close(s.dropD)
|
| 341 | 346 |
b.cancel()
|
| 342 | 347 |
return frame.err // b.frameCh is buffered it's ok to return here
|
| 343 | 348 |
}
|