github.com/maypok86/otter@v1.2.1/internal/s3fifo/small.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 type small[K comparable, V any] struct { 22 q *queue[K, V] 23 main *main[K, V] 24 ghost *ghost[K, V] 25 cost int 26 maxCost int 27 } 28 29 func newSmall[K comparable, V any]( 30 maxCost int, 31 main *main[K, V], 32 ghost *ghost[K, V], 33 ) *small[K, V] { 34 return &small[K, V]{ 35 q: newQueue[K, V](), 36 main: main, 37 ghost: ghost, 38 maxCost: maxCost, 39 } 40 } 41 42 func (s *small[K, V]) insert(n node.Node[K, V]) { 43 s.q.push(n) 44 n.MarkSmall() 45 s.cost += int(n.Cost()) 46 } 47 48 func (s *small[K, V]) evict(deleted []node.Node[K, V]) []node.Node[K, V] { 49 if s.cost == 0 { 50 return deleted 51 } 52 53 n := s.q.pop() 54 s.cost -= int(n.Cost()) 55 n.Unmark() 56 if !n.IsAlive() || n.HasExpired() { 57 return append(deleted, n) 58 } 59 60 if n.Frequency() > 1 { 61 s.main.insert(n) 62 for s.main.isFull() { 63 deleted = s.main.evict(deleted) 64 } 65 n.ResetFrequency() 66 return deleted 67 } 68 69 return s.ghost.insert(deleted, n) 70 } 71 72 func (s *small[K, V]) remove(n node.Node[K, V]) { 73 s.cost -= int(n.Cost()) 74 n.Unmark() 75 s.q.remove(n) 76 } 77 78 func (s *small[K, V]) length() int { 79 return s.q.length() 80 } 81 82 func (s *small[K, V]) clear() { 83 s.q.clear() 84 s.cost = 0 85 }