github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/util/evicting_queue.go (about)

     1  package util
     2  
     3  import (
     4  	"errors"
     5  	"sync"
     6  )
     7  
     8  type EvictingQueue struct {
     9  	sync.RWMutex
    10  
    11  	capacity int
    12  	entries  []interface{}
    13  	onEvict  func()
    14  }
    15  
    16  func NewEvictingQueue(capacity int, onEvict func()) (*EvictingQueue, error) {
    17  	if err := validateCapacity(capacity); err != nil {
    18  		return nil, err
    19  	}
    20  
    21  	queue := &EvictingQueue{
    22  		onEvict: onEvict,
    23  		entries: make([]interface{}, 0, capacity),
    24  	}
    25  
    26  	err := queue.SetCapacity(capacity)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	return queue, nil
    32  }
    33  
    34  func (q *EvictingQueue) Append(entry interface{}) {
    35  	q.Lock()
    36  	defer q.Unlock()
    37  
    38  	if len(q.entries) >= q.capacity {
    39  		q.evictOldest()
    40  	}
    41  
    42  	q.entries = append(q.entries, entry)
    43  }
    44  
    45  func (q *EvictingQueue) evictOldest() {
    46  	q.onEvict()
    47  
    48  	start := (len(q.entries) - q.Capacity()) + 1
    49  	q.entries = append(q.entries[:0], q.entries[start:]...)
    50  }
    51  
    52  func (q *EvictingQueue) Entries() []interface{} {
    53  	q.RLock()
    54  	defer q.RUnlock()
    55  
    56  	return q.entries
    57  }
    58  
    59  func (q *EvictingQueue) Length() int {
    60  	q.RLock()
    61  	defer q.RUnlock()
    62  
    63  	return len(q.entries)
    64  }
    65  
    66  func (q *EvictingQueue) Capacity() int {
    67  	return q.capacity
    68  }
    69  
    70  func (q *EvictingQueue) SetCapacity(capacity int) error {
    71  	if err := validateCapacity(capacity); err != nil {
    72  		return err
    73  	}
    74  
    75  	q.capacity = capacity
    76  	return nil
    77  }
    78  
    79  func (q *EvictingQueue) Clear() {
    80  	q.Lock()
    81  	defer q.Unlock()
    82  
    83  	q.entries = q.entries[:0]
    84  }
    85  
    86  func validateCapacity(capacity int) error {
    87  	if capacity <= 0 {
    88  		// a queue of 0 (or smaller) capacity is invalid
    89  		return errors.New("queue cannot have a zero or negative capacity")
    90  	}
    91  
    92  	return nil
    93  }