A better Rust ATProto crate
1use super::{KeyDate, KeyHashDate, ValueEntry};
2use crate::common::{
3 deque::{DeqNode, Deque},
4 CacheRegion,
5};
6
7use std::ptr::NonNull;
8use tagptr::TagNonNull;
9
10pub(crate) struct Deques<K> {
11 pub(crate) window: Deque<KeyHashDate<K>>, // Not used yet.
12 pub(crate) probation: Deque<KeyHashDate<K>>,
13 pub(crate) protected: Deque<KeyHashDate<K>>, // Not used yet.
14 pub(crate) write_order: Deque<KeyDate<K>>,
15}
16
17impl<K> Default for Deques<K> {
18 fn default() -> Self {
19 Self {
20 window: Deque::new(CacheRegion::Window),
21 probation: Deque::new(CacheRegion::MainProbation),
22 protected: Deque::new(CacheRegion::MainProtected),
23 write_order: Deque::new(CacheRegion::Other),
24 }
25 }
26}
27
28impl<K> Deques<K> {
29 pub(crate) fn clear(&mut self) {
30 self.window = Deque::new(CacheRegion::Window);
31 self.probation = Deque::new(CacheRegion::MainProbation);
32 self.protected = Deque::new(CacheRegion::MainProtected);
33 self.write_order = Deque::new(CacheRegion::Other);
34 }
35
36 pub(crate) fn push_back_ao<V>(
37 &mut self,
38 region: CacheRegion,
39 kh: KeyHashDate<K>,
40 entry: &mut ValueEntry<K, V>,
41 ) {
42 let node = Box::new(DeqNode::new(kh));
43 let node = match region {
44 CacheRegion::Window => self.window.push_back(node),
45 CacheRegion::MainProbation => self.probation.push_back(node),
46 CacheRegion::MainProtected => self.protected.push_back(node),
47 CacheRegion::Other => unreachable!(),
48 };
49 let tagged_node = TagNonNull::compose(node, region as usize);
50 entry.set_access_order_q_node(Some(tagged_node));
51 }
52
53 pub(crate) fn push_back_wo<V>(&mut self, kh: KeyDate<K>, entry: &mut ValueEntry<K, V>) {
54 let node = Box::new(DeqNode::new(kh));
55 let node = self.write_order.push_back(node);
56 entry.set_write_order_q_node(Some(node));
57 }
58
59 pub(crate) fn move_to_back_ao<V>(&mut self, entry: &ValueEntry<K, V>) {
60 if let Some(tagged_node) = entry.access_order_q_node() {
61 let (node, tag) = tagged_node.decompose();
62 let p = unsafe { node.as_ref() };
63 match tag.into() {
64 CacheRegion::Window if self.window.contains(p) => {
65 unsafe { self.window.move_to_back(node) };
66 }
67 CacheRegion::MainProbation if self.probation.contains(p) => {
68 unsafe { self.probation.move_to_back(node) };
69 }
70 CacheRegion::MainProtected if self.protected.contains(p) => {
71 unsafe { self.protected.move_to_back(node) };
72 }
73 _ => unreachable!(),
74 }
75 }
76 }
77
78 pub(crate) fn move_to_back_wo<V>(&mut self, entry: &ValueEntry<K, V>) {
79 let node = entry.write_order_q_node().unwrap();
80 let p = unsafe { node.as_ref() };
81 if self.write_order.contains(p) {
82 unsafe { self.write_order.move_to_back(node) };
83 }
84 }
85
86 pub(crate) fn unlink_ao<V>(&mut self, entry: &mut ValueEntry<K, V>) {
87 if let Some(node) = entry.take_access_order_q_node() {
88 self.unlink_node_ao(node);
89 }
90 }
91
92 pub(crate) fn unlink_ao_from_deque<V>(
93 deq_name: &str,
94 deq: &mut Deque<KeyHashDate<K>>,
95 entry: &mut ValueEntry<K, V>,
96 ) {
97 if let Some(node) = entry.take_access_order_q_node() {
98 unsafe { Self::unlink_node_ao_from_deque(deq_name, deq, node) };
99 }
100 }
101
102 pub(crate) fn unlink_wo<V>(deq: &mut Deque<KeyDate<K>>, entry: &mut ValueEntry<K, V>) {
103 if let Some(node) = entry.take_write_order_q_node() {
104 Self::unlink_node_wo(deq, node);
105 }
106 }
107
108 pub(crate) fn unlink_node_ao(&mut self, tagged_node: TagNonNull<DeqNode<KeyHashDate<K>>, 2>) {
109 unsafe {
110 match tagged_node.decompose_tag().into() {
111 CacheRegion::Window => {
112 Self::unlink_node_ao_from_deque("window", &mut self.window, tagged_node)
113 }
114 CacheRegion::MainProbation => {
115 Self::unlink_node_ao_from_deque("probation", &mut self.probation, tagged_node)
116 }
117 CacheRegion::MainProtected => {
118 Self::unlink_node_ao_from_deque("protected", &mut self.protected, tagged_node)
119 }
120 _ => unreachable!(),
121 }
122 }
123 }
124
125 unsafe fn unlink_node_ao_from_deque(
126 deq_name: &str,
127 deq: &mut Deque<KeyHashDate<K>>,
128 tagged_node: TagNonNull<DeqNode<KeyHashDate<K>>, 2>,
129 ) {
130 let (node, tag) = tagged_node.decompose();
131 if deq.region() == tag && deq.contains(node.as_ref()) {
132 // https://github.com/moka-rs/moka/issues/64
133 deq.unlink_and_drop(node);
134 } else {
135 panic!(
136 "unlink_node - node is not a member of {} deque. {:?}",
137 deq_name,
138 node.as_ref()
139 )
140 }
141 }
142
143 pub(crate) fn unlink_node_wo(deq: &mut Deque<KeyDate<K>>, node: NonNull<DeqNode<KeyDate<K>>>) {
144 unsafe {
145 let p = node.as_ref();
146 if deq.contains(p) {
147 // https://github.com/moka-rs/moka/issues/64
148 deq.unlink_and_drop(node);
149 } else {
150 panic!(
151 "unlink_node - node is not a member of write_order deque. {:?}",
152 p
153 )
154 }
155 }
156 }
157}