github.com/better-concurrent/guc@v0.0.0-20190520022744-eb29266403a1/priorityqueue.go (about) 1 package guc 2 3 import ( 4 "container/heap" 5 "unsafe" 6 ) 7 8 var _ Queue = new(PriorityQueue) 9 10 // we don't want to expose golang heap api to users 11 // so here we create a struct that implements heap api 12 type priorityData struct { 13 data []interface{} 14 queue *PriorityQueue 15 comparator Comparator 16 } 17 18 type PriorityQueue struct { 19 data priorityData 20 21 hashCode int 22 } 23 24 type priorityQueueIter struct { 25 idx int 26 data []interface{} 27 queue *PriorityQueue 28 } 29 30 func (this *priorityQueueIter) HasNext() bool { 31 this.idx++ 32 return this.idx < len(this.data) 33 } 34 35 func (this *priorityQueueIter) Next() interface{} { 36 r := this.data[this.idx] 37 return r 38 } 39 40 func (this *priorityQueueIter) Remove() { 41 heap.Remove(&this.queue.data, this.idx) 42 this.data = this.queue.data.data 43 this.idx-- 44 } 45 46 func (this *priorityQueueIter) ForEachRemaining(consumer func(i interface{})) { 47 for this.HasNext() { 48 consumer(this.Next()) 49 } 50 } 51 52 func NewPriority() *PriorityQueue { 53 queue := &PriorityQueue{ 54 data: priorityData{}, 55 } 56 queue.data.queue = queue 57 return queue 58 } 59 60 func NewPriorityWithComparator(comparator Comparator) *PriorityQueue { 61 queue := &PriorityQueue{ 62 data: priorityData{ 63 comparator: comparator, 64 }, 65 } 66 queue.data.queue = queue 67 return queue 68 } 69 70 func (this priorityData) Len() int { 71 return len(this.data) 72 } 73 74 func (this priorityData) Less(i, j int) bool { 75 c := this.comparator 76 data := this.data 77 if c != nil { 78 if c.Compare(data[i], data[j]) < 0 { 79 return true 80 } else { 81 return false 82 } 83 } else { 84 if data[i].(Comparable).CompareTo(data[j]) < 0 { 85 return true 86 } else { 87 return false 88 } 89 } 90 } 91 92 func (this priorityData) Swap(i, j int) { 93 data := this.data 94 data[j], data[i] = data[i], data[j] 95 } 96 97 func (this *priorityData) Push(x interface{}) { 98 this.data = append(this.data, x) 99 } 100 101 func (this *priorityData) Pop() interface{} { 102 old := this.data 103 n := len(old) 104 i := old[n-1] 105 old[n-1] = nil //clear index, in order to avoid memory leak 106 this.data = old[:n-1] 107 return i 108 } 109 110 func (this *PriorityQueue) Iterator() Iterator { 111 iter := new(priorityQueueIter) 112 iter.idx = -1 113 iter.data = this.data.data 114 iter.queue = this 115 return iter 116 } 117 118 func (this *PriorityQueue) ForEach(consumer func(i interface{})) { 119 for _, v := range this.data.data { 120 consumer(v) 121 } 122 } 123 124 func (this *PriorityQueue) Size() int { 125 return len(this.data.data) 126 } 127 128 func (this *PriorityQueue) IsEmpty() bool { 129 return len(this.data.data) == 0 130 } 131 132 func (this *PriorityQueue) Contains(i interface{}) bool { 133 data := this.data.data 134 for _, v := range data { 135 if v.(Object).Equals(i) { 136 return true 137 } 138 } 139 return false 140 } 141 142 func (this *PriorityQueue) ToArray() []interface{} { 143 data := this.data.data 144 result := make([]interface{}, 0, len(data)) 145 for _, v := range data { 146 result = append(result, v) 147 } 148 return result 149 } 150 151 func (this *PriorityQueue) FillArray(arr []interface{}) []interface{} { 152 data := this.data.data 153 if len(arr) >= len(data) { 154 for i, v := range data { 155 arr[i] = v 156 } 157 return arr[:len(data)] 158 } else { 159 return this.ToArray() 160 } 161 } 162 163 func (this *PriorityQueue) Add(i interface{}) bool { 164 heap.Push(&this.data, i) 165 return true 166 } 167 168 func (this *PriorityQueue) Remove(item interface{}) bool { 169 for i, v := range this.data.data { 170 if v.(Object).Equals(item) { 171 heap.Remove(&this.data, i) 172 return true 173 } 174 } 175 return false 176 } 177 178 func (this *PriorityQueue) ContainsAll(coll Collection) bool { 179 iter := coll.Iterator() 180 for iter.HasNext() { 181 if !this.Contains(iter.Next()) { 182 return false 183 } 184 } 185 return true 186 } 187 188 func (this *PriorityQueue) AddAll(coll Collection) bool { 189 changed := false 190 iter := coll.Iterator() 191 for iter.HasNext() { 192 changed = true 193 heap.Push(&this.data, iter.Next()) 194 } 195 return changed 196 } 197 198 func (this *PriorityQueue) RemoveAll(coll Collection) bool { 199 removed := false 200 iter := coll.Iterator() 201 for iter.HasNext() { 202 r := this.Remove(iter.Next()) 203 if r { 204 removed = true 205 } 206 } 207 return removed 208 } 209 210 func (this *PriorityQueue) RemoveIf(predicate func(i interface{}) bool) bool { 211 idx := -1 212 for i, v := range this.data.data { 213 if predicate(v) { 214 idx = i 215 break 216 } 217 } 218 if idx >= 0 { 219 heap.Remove(&this.data, idx) 220 return true 221 } else { 222 return false 223 } 224 } 225 226 func (this *PriorityQueue) RetainAll(coll Collection) bool { 227 iter := this.Iterator() 228 changed := false 229 for iter.HasNext() { 230 if !coll.Contains(iter.Next()) { 231 iter.Remove() 232 changed = true 233 } 234 } 235 return changed 236 } 237 238 func (this *PriorityQueue) Clear() { 239 this.data.data = make([]interface{}, 0) 240 } 241 242 func (this *PriorityQueue) Equals(i interface{}) bool { 243 p, ok := i.(*PriorityQueue) 244 if ok { 245 return p == this 246 } 247 return false 248 } 249 250 func (this *PriorityQueue) HashCode() int { 251 hashCode := this.hashCode 252 if hashCode != 0 { 253 return hashCode 254 } 255 hashCode = int(uintptr(unsafe.Pointer(this))) 256 this.hashCode = hashCode 257 return hashCode 258 } 259 260 func (this *PriorityQueue) Offer(i interface{}) bool { 261 heap.Push(&this.data, i) 262 return true 263 } 264 265 func (this *PriorityQueue) RemoveHead() interface{} { 266 var i interface{} = nil 267 if !this.IsEmpty() { 268 i = heap.Pop(&this.data) 269 } 270 if i == nil { 271 panic("queue is empty") 272 } 273 return i 274 } 275 276 func (this *PriorityQueue) Poll() interface{} { 277 if this.IsEmpty() { 278 return nil 279 } 280 i := heap.Pop(&this.data) 281 return i 282 } 283 284 func (this *PriorityQueue) Element() interface{} { 285 if this.IsEmpty() { 286 panic("queue is empty") 287 } else { 288 return this.data.data[0] 289 } 290 } 291 292 func (this *PriorityQueue) Peek() interface{} { 293 if this.IsEmpty() { 294 return nil 295 } else { 296 return this.data.data[0] 297 } 298 }