2023-05-10 13:50:04 +00:00
|
|
|
# nim-eth
|
2024-06-18 16:09:27 +00:00
|
|
|
# Copyright (c) 2020-2024 Status Research & Development GmbH
|
2023-05-10 13:50:04 +00:00
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
#
|
|
|
|
|
|
|
|
{.push raises: [].}
|
2020-09-10 12:49:48 +00:00
|
|
|
|
2024-06-18 16:09:27 +00:00
|
|
|
import std/[tables, lists], results
|
|
|
|
|
|
|
|
export results
|
2020-09-10 12:49:48 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
LRUCache*[K, V] = object of RootObj
|
|
|
|
list: DoublyLinkedList[(K, V)] # Head is MRU k:v and tail is LRU k:v
|
2022-11-16 16:44:00 +00:00
|
|
|
table: Table[K, DoublyLinkedNode[(K, V)]] # DoublyLinkedNode is already ref
|
2020-09-10 12:49:48 +00:00
|
|
|
capacity: int
|
|
|
|
|
2021-02-02 21:47:21 +00:00
|
|
|
func init*[K, V](T: type LRUCache[K, V], capacity: int): LRUCache[K, V] =
|
2020-09-10 12:49:48 +00:00
|
|
|
LRUCache[K, V](capacity: capacity) # Table and list init is done default
|
|
|
|
|
2024-06-18 16:09:27 +00:00
|
|
|
func get*[K, V](lru: var LRUCache[K, V], key: K): Opt[V] =
|
2020-09-10 12:49:48 +00:00
|
|
|
let node = lru.table.getOrDefault(key, nil)
|
|
|
|
if node.isNil:
|
2024-06-18 16:09:27 +00:00
|
|
|
return Opt.none(V)
|
2020-09-10 12:49:48 +00:00
|
|
|
|
|
|
|
lru.list.remove(node)
|
|
|
|
lru.list.prepend(node)
|
2024-06-18 16:09:27 +00:00
|
|
|
return Opt.some(node.value[1])
|
2020-09-10 12:49:48 +00:00
|
|
|
|
2021-02-02 21:47:21 +00:00
|
|
|
func put*[K, V](lru: var LRUCache[K, V], key: K, value: V) =
|
2020-09-10 12:49:48 +00:00
|
|
|
let node = lru.table.getOrDefault(key, nil)
|
|
|
|
if not node.isNil:
|
|
|
|
lru.list.remove(node)
|
|
|
|
else:
|
|
|
|
if lru.table.len >= lru.capacity:
|
|
|
|
lru.table.del(lru.list.tail.value[0])
|
|
|
|
lru.list.remove(lru.list.tail)
|
|
|
|
|
|
|
|
lru.list.prepend((key, value))
|
|
|
|
lru.table[key] = lru.list.head
|
|
|
|
|
2021-02-02 21:47:21 +00:00
|
|
|
func del*[K, V](lru: var LRUCache[K, V], key: K) =
|
2020-09-10 12:49:48 +00:00
|
|
|
var node: DoublyLinkedNode[(K, V)]
|
|
|
|
if lru.table.pop(key, node):
|
|
|
|
lru.list.remove(node)
|
|
|
|
|
2021-02-02 21:47:21 +00:00
|
|
|
func len*[K, V](lru: LRUCache[K, V]): int =
|
2020-09-10 12:49:48 +00:00
|
|
|
lru.table.len
|