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;
9use triomphe::Arc as TrioArc;
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 push_back_ao<V>(
30 &mut self,
31 region: CacheRegion,
32 khd: KeyHashDate<K>,
33 entry: &TrioArc<ValueEntry<K, V>>,
34 ) {
35 let node = Box::new(DeqNode::new(khd));
36 let node = match region {
37 CacheRegion::Window => self.window.push_back(node),
38 CacheRegion::MainProbation => self.probation.push_back(node),
39 CacheRegion::MainProtected => self.protected.push_back(node),
40 _ => unreachable!(),
41 };
42 let tagged_node = TagNonNull::compose(node, region as usize);
43 entry.set_access_order_q_node(Some(tagged_node));
44 }
45
46 pub(crate) fn push_back_wo<V>(&mut self, kd: KeyDate<K>, entry: &TrioArc<ValueEntry<K, V>>) {
47 let node = Box::new(DeqNode::new(kd));
48 let node = self.write_order.push_back(node);
49 entry.set_write_order_q_node(Some(node));
50 }
51
52 pub(crate) fn move_to_back_ao<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
53 if let Some(tagged_node) = entry.access_order_q_node() {
54 let (node, tag) = tagged_node.decompose();
55 let p = unsafe { node.as_ref() };
56 match tag.into() {
57 CacheRegion::Window if self.window.contains(p) => {
58 unsafe { self.window.move_to_back(node) };
59 }
60 CacheRegion::MainProbation if self.probation.contains(p) => {
61 unsafe { self.probation.move_to_back(node) };
62 }
63 CacheRegion::MainProtected if self.protected.contains(p) => {
64 unsafe { self.protected.move_to_back(node) };
65 }
66 _ => unreachable!(),
67 }
68 }
69 }
70
71 pub(crate) fn move_to_back_ao_in_deque<V>(
72 deq_name: &str,
73 deq: &mut Deque<KeyHashDate<K>>,
74 entry: &TrioArc<ValueEntry<K, V>>,
75 ) {
76 if let Some(tagged_node) = entry.access_order_q_node() {
77 let (node, tag) = tagged_node.decompose();
78 let p = unsafe { node.as_ref() };
79 if deq.region() == tag {
80 if deq.contains(p) {
81 unsafe { deq.move_to_back(node) };
82 }
83 } else {
84 panic!(
85 "move_to_back_ao_in_deque - node is not a member of {} deque. {:?}",
86 deq_name, p,
87 )
88 }
89 }
90 }
91
92 pub(crate) fn move_to_back_wo<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
93 if let Some(node) = entry.write_order_q_node() {
94 let p = unsafe { node.as_ref() };
95 if self.write_order.contains(p) {
96 unsafe { self.write_order.move_to_back(node) };
97 }
98 }
99 }
100
101 pub(crate) fn move_to_back_wo_in_deque<V>(
102 deq: &mut Deque<KeyDate<K>>,
103 entry: &TrioArc<ValueEntry<K, V>>,
104 ) {
105 if let Some(node) = entry.write_order_q_node() {
106 let p = unsafe { node.as_ref() };
107 if deq.contains(p) {
108 unsafe { deq.move_to_back(node) };
109 }
110 }
111 }
112
113 pub(crate) fn unlink_ao<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
114 if let Some(node) = entry.take_access_order_q_node() {
115 self.unlink_node_ao(node);
116 }
117 }
118
119 pub(crate) fn unlink_ao_from_deque<V>(
120 deq_name: &str,
121 deq: &mut Deque<KeyHashDate<K>>,
122 entry: &TrioArc<ValueEntry<K, V>>,
123 ) {
124 if let Some(node) = entry.take_access_order_q_node() {
125 unsafe { Self::unlink_node_ao_from_deque(deq_name, deq, node) };
126 }
127 }
128
129 pub(crate) fn unlink_wo<V>(deq: &mut Deque<KeyDate<K>>, entry: &TrioArc<ValueEntry<K, V>>) {
130 if let Some(node) = entry.take_write_order_q_node() {
131 Self::unlink_node_wo(deq, node);
132 }
133 }
134
135 pub(crate) fn unlink_node_ao(&mut self, tagged_node: TagNonNull<DeqNode<KeyHashDate<K>>, 2>) {
136 unsafe {
137 match tagged_node.decompose_tag().into() {
138 CacheRegion::Window => {
139 Self::unlink_node_ao_from_deque("window", &mut self.window, tagged_node)
140 }
141 CacheRegion::MainProbation => {
142 Self::unlink_node_ao_from_deque("probation", &mut self.probation, tagged_node)
143 }
144 CacheRegion::MainProtected => {
145 Self::unlink_node_ao_from_deque("protected", &mut self.protected, tagged_node)
146 }
147 _ => unreachable!(),
148 }
149 }
150 }
151
152 unsafe fn unlink_node_ao_from_deque(
153 deq_name: &str,
154 deq: &mut Deque<KeyHashDate<K>>,
155 tagged_node: TagNonNull<DeqNode<KeyHashDate<K>>, 2>,
156 ) {
157 let (node, tag) = tagged_node.decompose();
158 let p = node.as_ref();
159 if deq.region() == tag {
160 if deq.contains(p) {
161 // https://github.com/moka-rs/moka/issues/64
162 deq.unlink_and_drop(node);
163 }
164 } else {
165 panic!(
166 "unlink_node - node is not a member of {} deque. {:?}",
167 deq_name, p
168 )
169 }
170 }
171
172 pub(crate) fn unlink_node_wo(deq: &mut Deque<KeyDate<K>>, node: NonNull<DeqNode<KeyDate<K>>>) {
173 unsafe {
174 let p = node.as_ref();
175 if deq.contains(p) {
176 // https://github.com/moka-rs/moka/issues/64
177 deq.unlink_and_drop(node);
178 }
179 }
180 }
181}