github.com/maypok86/otter@v1.2.1/internal/s3fifo/main.go (about) 1 // Copyright (c) 2023 Alexey Mayshev. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package s3fifo 16 17 import ( 18 "github.com/maypok86/otter/internal/generated/node" 19 ) 20 21 const maxReinsertions = 20 22 23 type main[K comparable, V any] struct { 24 q *queue[K, V] 25 cost int 26 maxCost int 27 } 28 29 func newMain[K comparable, V any](maxCost int) *main[K, V] { 30 return &main[K, V]{ 31 q: newQueue[K, V](), 32 maxCost: maxCost, 33 } 34 } 35 36 func (m *main[K, V]) insert(n node.Node[K, V]) { 37 m.q.push(n) 38 n.MarkMain() 39 m.cost += int(n.Cost()) 40 } 41 42 func (m *main[K, V]) evict(deleted []node.Node[K, V]) []node.Node[K, V] { 43 reinsertions := 0 44 for m.cost > 0 { 45 n := m.q.pop() 46 47 if !n.IsAlive() || n.HasExpired() || n.Frequency() == 0 { 48 n.Unmark() 49 m.cost -= int(n.Cost()) 50 return append(deleted, n) 51 } 52 53 // to avoid the worst case O(n), we remove the 20th reinserted consecutive element. 54 reinsertions++ 55 if reinsertions >= maxReinsertions { 56 n.Unmark() 57 m.cost -= int(n.Cost()) 58 return append(deleted, n) 59 } 60 61 m.q.push(n) 62 n.DecrementFrequency() 63 } 64 return deleted 65 } 66 67 func (m *main[K, V]) remove(n node.Node[K, V]) { 68 m.cost -= int(n.Cost()) 69 n.Unmark() 70 m.q.remove(n) 71 } 72 73 func (m *main[K, V]) length() int { 74 return m.q.length() 75 } 76 77 func (m *main[K, V]) clear() { 78 m.q.clear() 79 m.cost = 0 80 } 81 82 func (m *main[K, V]) isFull() bool { 83 return m.cost >= m.maxCost 84 }