zakhar_azg

Untitled

Dec 6th, 2024
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 10.90 KB | None | 0 0
  1. use alloc::{
  2.     collections::{BTreeMap, LinkedList},
  3.     vec::Vec,
  4. };
  5. use core::{cmp::Ord, fmt, mem};
  6.  
  7.  
  8. /// Реализация политики вытеснения давно неиспользуемых данных
  9. /// ([Least Recently Used (LRU)](https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU)).
  10. ///
  11. /// Предполагает, что ключ `K` и значение `V` --- легковесные типы.
  12. /// А сам кеш хранит своё содержимое где-то в другом месте.
  13. #[derive(Clone, Debug)]
  14. pub struct Lru<K, V>
  15. where
  16.     K: Clone + Copy + Ord,
  17.     V: Clone + Copy,
  18. {
  19.     /// Отображение ключей в индексы, по которым хранятся узлы со значениями.
  20.     /// То есть, значения [`Lru::map`] --- это индексы в [`Lru::nodes`].
  21.     map: BTreeMap<K, usize>,
  22.  
  23.     /// Хранилище для узлов, отображающих ключи в значения.
  24.     /// Эти же узлы провязаны в LRU--очередь на основе двусвязного списка.
  25.     /// LRU--очередь перечисляет узлы в порядке их последнего использования,
  26.     /// от дольше всего не использовавшегося до использованного последним.
  27.     nodes: Vec<Node<K, V>>,
  28.  
  29.     /// Голова LRU--очереди --- узел, который не использовался дольше всего.
  30.     head: Option<usize>,
  31.  
  32.     /// Хвост LRU--очереди --- узел, который использовался последним.
  33.     tail: Option<usize>,
  34. }
  35.  
  36.  
  37. #[derive(Clone, Debug)]
  38. /// Узел LRU--очереди.
  39. ///
  40. /// LRU--очередь перечисляет узлы в порядке их последнего использования,
  41. /// от дольше всего не использовавшегося до использованного последним.
  42. struct Node<K, V> {
  43.     /// Ключ.
  44.     key: K,
  45.  
  46.     /// Значение.
  47.     value: V,
  48.  
  49.     /// Предыщущий узел, он использовался последний раз перед последним использованием текущего.
  50.     /// Хранится как индекс в [`Lru::nodes`].
  51.     prev: Option<usize>,
  52.  
  53.     /// Следующий узел, он использовался последний раз после последнего использования текущего.
  54.     /// Хранится как индекс в [`Lru::nodes`].
  55.     next: Option<usize>,
  56. }
  57.  
  58.  
  59. impl<K, V> Lru<K, V>
  60. where
  61.     K: Clone + Copy + Ord,
  62.     V: Clone + Copy,
  63. {
  64.     /// Создаёт LRU--кеш с ограничением на ёмкость `capacity`.
  65.     ///
  66.     /// # Panics
  67.     ///
  68.     /// Паникует, если ограничение на ёмкость нулевое.
  69.     pub fn new(capacity: usize) -> Self {
  70.         assert!(capacity > 0);
  71.  
  72.         Self {
  73.             nodes: Vec::with_capacity(capacity),
  74.             map: BTreeMap::new(),
  75.             head: None,
  76.             tail: None,
  77.         }
  78.     }
  79.  
  80.  
  81.     /// Сохраняет в кеш заданную пару ключ--значение.
  82.     /// Обновляет время доступа к записи, если она есть.
  83.     /// Возвращает:
  84.     ///   - Пару ключ--значение, которую при этом пришлось вытеснить из кеша,
  85.     ///     если до операции уже было достигнуто ограничение на его текущую ёмкость.
  86.     ///   - [`None`], если ограничение на текущую ёмкость кеша
  87.     ///     не было достигнуто на момент начала операции.
  88.     pub fn insert(&mut self, key: K, value: V) -> Option<(K, V)> {
  89.         if self.map.contains_key(&key) {
  90.             self.get(key).unwrap();
  91.             return None;
  92.         }
  93.  
  94.         let mut poped = None;
  95.         if self.nodes.len() == self.nodes.capacity() {
  96.             poped = self.pop();
  97.             poped.unwrap();
  98.         }
  99.  
  100.         assert!(self.nodes.len() < self.nodes.capacity());
  101.         let node = Node::<K, V> {
  102.             key,
  103.             value,
  104.             prev: self.tail,
  105.             next: None,
  106.         };
  107.         self.nodes.push(node);
  108.         self.tail = Some(self.nodes.len() - 1);
  109.         self.map.insert(key, self.tail.unwrap());
  110.  
  111.         if self.head.is_none() {
  112.             self.head = self.tail;
  113.         } else {
  114.             let prev = self.nodes[self.tail.unwrap()].prev.unwrap();
  115.             self.nodes[prev].next = self.tail;
  116.         }
  117.  
  118.         poped
  119.     }
  120.  
  121.  
  122.     /// Возвращает значение для заданного ключа `key`,
  123.     /// или [`None`], если соответствующей записи нет.
  124.     /// Обновляет время доступа к записи, если она есть.
  125.     pub fn get(&mut self, key: K) -> Option<V> {
  126.         let maybe_id = self.map.get(&key);
  127.         if maybe_id.is_none() {
  128.             return None;
  129.         }
  130.         let id = *maybe_id.unwrap();
  131.  
  132.         self.set_next_in_prev(id, self.nodes[id].next);
  133.         self.set_prev_in_next(id, self.nodes[id].prev);
  134.  
  135.         let old_tail = self.tail;
  136.         {
  137.             let node = self.nodes.get_mut(id).unwrap();
  138.             self.tail = Some(id);
  139.             node.prev = old_tail;
  140.             node.next = None;
  141.         }
  142.  
  143.         if let Some(old_tail) = old_tail {
  144.             self.nodes.get_mut(old_tail).unwrap().next = Some(id);
  145.         }
  146.  
  147.         Some(self.nodes[id].value)
  148.     }
  149.  
  150.  
  151.     /// Удаляет из кеша запись с заданным ключём `key`, если она есть.
  152.     /// Возвращает:
  153.     ///   - Значение для удалённого ключа.
  154.     ///   - [`None`], если по ключу `key` в кеше ничего не найдено.
  155.     pub fn remove(&mut self, key: K) -> Option<V> {
  156.         // info!("in remove");
  157.         let maybe_id = self.map.get(&key);
  158.         if maybe_id.is_none() {
  159.             return None;
  160.         }
  161.         let id = *maybe_id.unwrap();
  162.  
  163.         Some(self.remove_node(id).unwrap().1)
  164.     }
  165.  
  166.  
  167.     /// Удаляет из кеша запись, которая дольше всех остальных не обновлялась.
  168.     /// Возвращает удалённую пару ключ--значение.
  169.     fn pop(&mut self) -> Option<(K, V)> {
  170.         if let Some(id) = self.head {
  171.             self.remove_node(id)
  172.         } else {
  173.             None
  174.         }
  175.     }
  176.  
  177.  
  178.     /// Удаляет из кеша запись по её индексу `id` в [`Lru::nodes`].
  179.     /// Возвращает удалённую пару ключ--значение.
  180.     fn remove_node(&mut self, id: usize) -> Option<(K, V)> {
  181.         self.map.remove(&self.nodes[id].key).unwrap();
  182.  
  183.         self.set_next_in_prev(id, self.nodes[id].next);
  184.         self.set_prev_in_next(id, self.nodes[id].prev);
  185.  
  186.         let sz = self.nodes.len();
  187.         if id != sz - 1 {
  188.             self.nodes.swap(id, sz - 1);
  189.  
  190.             self.set_next_in_prev(id, Some(id));
  191.             self.set_prev_in_next(id, Some(id));
  192.  
  193.             self.map.insert(self.nodes[id].key, id).unwrap();
  194.  
  195.             if self.head.unwrap() == sz - 1 {
  196.                 self.head = Some(id);
  197.             }
  198.             if self.tail.unwrap() == sz - 1 {
  199.                 self.tail = Some(id);
  200.             }
  201.         }
  202.  
  203.         let node = self.nodes.pop().unwrap();
  204.  
  205.         Some((node.key, node.value))
  206.     }
  207.  
  208.  
  209.     /// Устанавливает в `next` ссылку [`Node::next`] узла,
  210.     /// который предшествует узлу номер `id` в структуре очереди,
  211.     /// либо обновляет [`Lru::head`], если предшествующего узла нет.
  212.     fn set_next_in_prev(&mut self, id: usize, next: Option<usize>) {
  213.         let node = self.nodes.get(id).unwrap();
  214.  
  215.         if let Some(prev_node) = node.prev {
  216.             self.nodes[prev_node].next = next;
  217.         } else {
  218.             self.head = next;
  219.         }
  220.     }
  221.  
  222.  
  223.     /// Устанавливает в `prev` ссылку [`Node::prev`] узла,
  224.     /// который следует за узлом номер `id` в структуре очереди,
  225.     /// либо обновляет [`Lru::tail`], если следующего узла нет.
  226.     fn set_prev_in_next(&mut self, id: usize, prev: Option<usize>) {
  227.         let node = self.nodes.get(id).unwrap();
  228.  
  229.         if let Some(next_node) = node.next {
  230.             self.nodes[next_node].prev = prev;
  231.         } else {
  232.             self.tail = prev;
  233.         }
  234.     }
  235.  
  236.  
  237.     /// Проверяет внутренние инварианты LRU--кеша
  238.     ///
  239.     /// # Panics
  240.     ///
  241.     /// Паникует, если инварианты нарушены.
  242.     pub fn validate(&self) {
  243.         let mut curr = self.head;
  244.         let mut prev = None;
  245.         let mut tail = None;
  246.         let mut count = 0;
  247.  
  248.         assert_eq!(self.nodes.len(), self.map.len());
  249.         assert!(self.nodes.len() <= self.nodes.capacity());
  250.  
  251.         while let Some(id) = curr {
  252.             assert!(count < self.nodes.len());
  253.             assert!(id < self.nodes.len());
  254.  
  255.             let node = &self.nodes[id];
  256.  
  257.             assert_eq!(node.prev, prev);
  258.             assert_eq!(self.map.get(&node.key), Some(&id));
  259.  
  260.             prev = curr;
  261.             curr = node.next;
  262.             if curr.is_none() {
  263.                 tail = Some(id);
  264.             }
  265.  
  266.             count += 1;
  267.         }
  268.  
  269.         assert_eq!(self.tail, tail);
  270.     }
  271. }
  272.  
  273.  
  274. impl<K, V> fmt::Display for Lru<K, V>
  275. where
  276.     K: Clone + Copy + Ord + fmt::Display,
  277.     V: Clone + Copy + fmt::Display,
  278. {
  279.     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  280.         write!(
  281.             formatter,
  282.             "head: {:?}, tail: {:?}, lru: [",
  283.             self.head, self.tail,
  284.         )?;
  285.  
  286.         let mut separator = "";
  287.         let mut curr = self.head;
  288.  
  289.         while let Some(id) = curr {
  290.             let node = &self.nodes[id];
  291.  
  292.             write!(
  293.                 formatter,
  294.                 "{}{{id: {}, key: {}, value: {}, prev: {:?}, next: {:?}}}",
  295.                 separator, id, node.key, node.value, node.prev, node.next,
  296.             )?;
  297.  
  298.             curr = node.next;
  299.             separator = ", ";
  300.         }
  301.  
  302.         write!(formatter, "], map: {{")?;
  303.  
  304.         separator = "";
  305.         for (key, id) in self.map.iter() {
  306.             let value = &self.nodes[*id].value;
  307.             write!(formatter, "{}{} -> {} [{}]", separator, key, value, id)?;
  308.             separator = ", ";
  309.         }
  310.  
  311.         write!(formatter, "}}")
  312.     }
  313. }
  314.  
Advertisement
Add Comment
Please, Sign In to add comment