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  }