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  }