11from dataclasses import dataclass
22from threading import RLock
3- from typing import Any , Hashable , Optional
3+ from typing import Any , Hashable , Optional , Set
44
5- from llist import dllistnode , dllist
5+
6+ @dataclass (unsafe_hash = True )
7+ class Node :
8+ prev : Optional ["Node" ]
9+ next : Optional ["Node" ]
10+ items : Set ["Item" ]
611
712
813@dataclass (frozen = True )
9- class FrequencyItem :
10- node : dllistnode
14+ class Item :
15+ node : Node
1116 key : Hashable
1217 value : Any
1318
@@ -28,48 +33,53 @@ class LFUCache:
2833
2934 def __init__ (self , max_size : int = 0 ):
3035 self .cache = dict ()
31- self .usages = dllist ( )
36+ self .usages : Node = Node ( prev = None , next = None , items = set () )
3237 self .lock = RLock ()
3338 self .size = 0
3439 self .max_size = max_size
3540
36- def _create_node (self ) -> dllistnode :
37- return self .usages .append (set ([]))
41+ def _create_node (self ) -> Node :
42+ node = Node (prev = self .usages , next = None , items = set ())
43+ self .usages .next = node
44+ return node
3845
39- def _update_usage (self , item : FrequencyItem ):
46+ def _update_usage (self , item : Item ):
4047 with self .lock :
4148 old_node = item .node
4249 new_node = item .node .next
4350
4451 if new_node is None :
4552 new_node = self ._create_node ()
4653
47- old_node .value .remove (item )
48- item = FrequencyItem (
54+ old_node .items .remove (item )
55+ item = Item (
4956 node = new_node ,
5057 key = item .key ,
5158 value = item .value ,
5259 )
53- new_node .value .add (item )
60+ new_node .items .add (item )
5461 self .cache [item .key ] = item
5562
56- if not old_node .value :
57- self .usages .remove (old_node )
63+ if not old_node .items :
64+ old_node .next = None
65+ old_node .prev = None
66+ self .usages = new_node
67+ self .usages .prev = None
5868
5969 def get (self , key : Hashable ):
60- item : FrequencyItem = self .cache [key ]
70+ item : Item = self .cache [key ]
6171 self ._update_usage (item )
6272 return item .value
6373
6474 def set (self , key : Hashable , value : Any ):
6575 with self .lock :
66- node : Optional [dllistnode ] = self .usages . first
76+ node : Optional [Node ] = self .usages
6777
6878 if node is None :
6979 node = self ._create_node ()
7080
71- item = FrequencyItem (node = node , key = key , value = value )
72- node .value .add (item )
81+ item = Item (node = node , key = key , value = value )
82+ node .items .add (item )
7383 self .cache [key ] = item
7484
7585 def __contains__ (self , key ) -> Any :
0 commit comments