1919
2020@dataclass (frozen = True )
2121class _LinkedListValue (Generic [_TKey ]):
22- __slots__ = ("key " , "time_ " )
22+ __slots__ = ("expire_at " , "key " )
2323
24- time_ : float
24+ expire_at : float
2525 key : _TKey
2626
2727 def __repr__ (self ) -> str : # pragma: no cover
28- return f"{ self .__class__ .__name__ } (time_ ={ self .time_ } , key={ self .key } )"
28+ return f"{ self .__class__ .__name__ } (expire_at ={ self .expire_at } , key={ self .key } )"
2929
3030
3131@dataclass (frozen = True )
@@ -69,7 +69,7 @@ def __init__(
6969 self ._ll_head : DoubleLinkedListNode [_LinkedListValue [_TKey ]] | None = None
7070 self ._ll_end : DoubleLinkedListNode [_LinkedListValue [_TKey ]] | None = None
7171 self ._max_size = max_size
72- self ._ttl = ttl
72+ self ._ttl = ttl . total_seconds () if ttl is not None else None
7373 self ._update_ttl_on_get = update_ttl_on_get
7474 self ._lock = Lock ()
7575
@@ -97,9 +97,9 @@ def _update_by_ttl(self, current_time: float | None = None) -> None:
9797 """Remove items that have expired."""
9898 if self ._ttl is None :
9999 return
100- current_time = current_time if current_time is not None else time .time ()
100+ current_time = current_time if current_time is not None else time .monotonic ()
101101 while self ._ll_head is not None :
102- if self ._ll_head .value .time_ + self . _ttl . total_seconds () >= current_time :
102+ if self ._ll_head .value .expire_at >= current_time :
103103 break
104104 del self ._dict [self ._ll_head .value .key ]
105105 self ._pop_ll_node (self ._ll_head )
@@ -136,9 +136,9 @@ def _put_node_to_end(self, node: DoubleLinkedListNode[_LinkedListValue[_TKey]])
136136 node .prev = self ._ll_end
137137 self ._ll_end = node
138138
139- def _setitem (self , __key : _TKey , __value : _TValue , time_ : float , / ) -> None :
139+ def _setitem (self , __key : _TKey , __value : _TValue , expire_at : float | None , / ) -> None :
140140 """Set an item in the dictionary and put it to the end of the linked list."""
141- new_node = DoubleLinkedListNode (value = _LinkedListValue (time_ = time_ , key = __key ))
141+ new_node = DoubleLinkedListNode (value = _LinkedListValue (expire_at = expire_at , key = __key ))
142142
143143 if (item := self ._dict .get (__key , None )) is not None :
144144 self ._pop_ll_node (item .node )
@@ -155,9 +155,10 @@ def _delitem(self, item: _DictValue[_TKey, _TValue]) -> None:
155155
156156 def __setitem__ (self , __key : _TKey , __value : _TValue , / ) -> None :
157157 with self ._lock :
158- time_ = time .time ()
159- self ._setitem (__key , __value , time_ )
160- self ._update_by_ttl (current_time = time_ )
158+ current_time = time .monotonic ()
159+ expire_at = current_time + self ._ttl if self ._ttl is not None else None
160+ self ._setitem (__key , __value , expire_at )
161+ self ._update_by_ttl (current_time = current_time )
161162 self ._update_by_size ()
162163
163164 def __delitem__ (self , __key : _TKey , / ) -> None :
@@ -168,11 +169,11 @@ def __delitem__(self, __key: _TKey, /) -> None:
168169
169170 def __getitem__ (self , __key : _TKey , / ) -> _TValue :
170171 with self ._lock :
171- time_ = time .time ()
172- self ._update_by_ttl (current_time = time_ )
172+ current_time = time .monotonic ()
173+ self ._update_by_ttl (current_time = current_time )
173174 item = self ._dict [__key ].value
174- if self ._update_ttl_on_get :
175- self ._setitem (__key , item , time_ )
175+ if self ._update_ttl_on_get and self . _ttl is not None :
176+ self ._setitem (__key , item , current_time + self . _ttl )
176177 return item
177178
178179 def __len__ (self ) -> int :
0 commit comments