github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/ttlcache/expiration_queue.go (about) 1 package ttlcache 2 3 import ( 4 "container/heap" 5 "container/list" 6 ) 7 8 // expirationQueue stores items that are ordered by their expiration 9 // timestamps. The 0th item is closest to its expiration. 10 type expirationQueue[K comparable, V any] []*list.Element 11 12 // newExpirationQueue creates and initializes a new expiration queue. 13 func newExpirationQueue[K comparable, V any]() expirationQueue[K, V] { 14 q := make(expirationQueue[K, V], 0) 15 heap.Init(&q) 16 return q 17 } 18 19 // isEmpty checks if the queue is empty. 20 func (q expirationQueue[K, V]) isEmpty() bool { 21 return q.Len() == 0 22 } 23 24 // update updates an existing item's value and position in the queue. 25 func (q *expirationQueue[K, V]) update(elem *list.Element) { 26 heap.Fix(q, elem.Value.(*Item[K, V]).queueIndex) 27 } 28 29 // push pushes a new item into the queue and updates the order of its 30 // elements. 31 func (q *expirationQueue[K, V]) push(elem *list.Element) { 32 heap.Push(q, elem) 33 } 34 35 // remove removes an item from the queue and updates the order of its 36 // elements. 37 func (q *expirationQueue[K, V]) remove(elem *list.Element) { 38 heap.Remove(q, elem.Value.(*Item[K, V]).queueIndex) 39 } 40 41 // Len returns the total number of items in the queue. 42 func (q expirationQueue[K, V]) Len() int { 43 return len(q) 44 } 45 46 // Less checks if the item at the i position expires sooner than 47 // the one at the j position. 48 func (q expirationQueue[K, V]) Less(i, j int) bool { 49 item1, item2 := q[i].Value.(*Item[K, V]), q[j].Value.(*Item[K, V]) 50 if item1.expiresAt.IsZero() { 51 return false 52 } 53 54 if item2.expiresAt.IsZero() { 55 return true 56 } 57 58 return item1.expiresAt.Before(item2.expiresAt) 59 } 60 61 // Swap switches the places of two queue items. 62 func (q expirationQueue[K, V]) Swap(i, j int) { 63 q[i], q[j] = q[j], q[i] 64 q[i].Value.(*Item[K, V]).queueIndex = i 65 q[j].Value.(*Item[K, V]).queueIndex = j 66 } 67 68 // Push appends a new item to the item slice. 69 func (q *expirationQueue[K, V]) Push(x interface{}) { 70 elem := x.(*list.Element) 71 elem.Value.(*Item[K, V]).queueIndex = len(*q) 72 *q = append(*q, elem) 73 } 74 75 // Pop removes and returns the last item. 76 func (q *expirationQueue[K, V]) Pop() interface{} { 77 old := *q 78 i := len(old) - 1 79 elem := old[i] 80 elem.Value.(*Item[K, V]).queueIndex = -1 81 old[i] = nil // avoid memory leak 82 *q = old[:i] 83 84 return elem 85 }