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