1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
package mpb
import "container/heap"
type heapManager chan heapRequest
type heapCmd int
const (
h_sync heapCmd = iota
h_push
h_iter
h_drain
h_fix
h_state
h_end
)
type heapRequest struct {
cmd heapCmd
data interface{}
}
type iterData struct {
iter chan<- *Bar
drop <-chan struct{}
}
type pushData struct {
bar *Bar
sync bool
}
type fixData struct {
bar *Bar
priority int
lazy bool
}
func (m heapManager) run() {
var bHeap priorityQueue
var pMatrix, aMatrix map[int][]chan int
var l int
var sync bool
for req := range m {
switch req.cmd {
case h_push:
data := req.data.(pushData)
heap.Push(&bHeap, data.bar)
if !sync {
sync = data.sync
}
case h_sync:
if sync || l != bHeap.Len() {
pMatrix = make(map[int][]chan int)
aMatrix = make(map[int][]chan int)
for _, b := range bHeap {
table := b.wSyncTable()
for i, ch := range table[0] {
pMatrix[i] = append(pMatrix[i], ch)
}
for i, ch := range table[1] {
aMatrix[i] = append(aMatrix[i], ch)
}
}
sync = false
l = bHeap.Len()
}
drop := req.data.(<-chan struct{})
syncWidth(pMatrix, drop)
syncWidth(aMatrix, drop)
case h_iter:
data := req.data.(iterData)
drop_iter:
for _, b := range bHeap {
select {
case data.iter <- b:
case <-data.drop:
break drop_iter
}
}
close(data.iter)
case h_drain:
data := req.data.(iterData)
drop_drain:
for bHeap.Len() != 0 {
select {
case data.iter <- heap.Pop(&bHeap).(*Bar):
case <-data.drop:
break drop_drain
}
}
close(data.iter)
case h_fix:
data := req.data.(fixData)
if data.bar.index < 0 {
break
}
data.bar.priority = data.priority
if !data.lazy {
heap.Fix(&bHeap, data.bar.index)
}
case h_state:
ch := req.data.(chan<- bool)
ch <- sync || l != bHeap.Len()
case h_end:
ch := req.data.(chan<- interface{})
if ch != nil {
go func() {
ch <- []*Bar(bHeap)
}()
}
close(m)
}
}
}
func (m heapManager) sync(drop <-chan struct{}) {
m <- heapRequest{cmd: h_sync, data: drop}
}
func (m heapManager) push(b *Bar, sync bool) {
data := pushData{b, sync}
m <- heapRequest{cmd: h_push, data: data}
}
func (m heapManager) iter(iter chan<- *Bar, drop <-chan struct{}) {
data := iterData{iter, drop}
m <- heapRequest{cmd: h_iter, data: data}
}
func (m heapManager) drain(iter chan<- *Bar, drop <-chan struct{}) {
data := iterData{iter, drop}
m <- heapRequest{cmd: h_drain, data: data}
}
func (m heapManager) fix(b *Bar, priority int, lazy bool) {
data := fixData{b, priority, lazy}
m <- heapRequest{cmd: h_fix, data: data}
}
func (m heapManager) state(ch chan<- bool) {
m <- heapRequest{cmd: h_state, data: ch}
}
func (m heapManager) end(ch chan<- interface{}) {
m <- heapRequest{cmd: h_end, data: ch}
}
func syncWidth(matrix map[int][]chan int, drop <-chan struct{}) {
for _, column := range matrix {
go maxWidthDistributor(column, drop)
}
}
func maxWidthDistributor(column []chan int, drop <-chan struct{}) {
var maxWidth int
for _, ch := range column {
select {
case w := <-ch:
if w > maxWidth {
maxWidth = w
}
case <-drop:
return
}
}
for _, ch := range column {
ch <- maxWidth
}
}
|