1use core::ops::Deref;
4
5use crate::{
6 arc::{ArcPtr, NonNullArcPtr},
7 atomic::{AtomicArcPtr, AtomicOptionArcPtr},
8 domain::Domain,
9 write_policy::WritePolicy,
10};
11
12pub trait AtomicArcRef {
14 type Arc;
16 type Owned;
20 type LoadCached<'a>
22 where
23 Self::Arc: 'a;
24 fn load_owned(&self) -> Self::Owned;
28 fn load_cached<'a>(&self, cached: &'a mut Self::Owned) -> Self::LoadCached<'a>;
32}
33
34impl<A: ArcPtr, D: Domain, W: WritePolicy> AtomicArcRef for AtomicArcPtr<A, D, W> {
35 type Arc = A;
36 type Owned = A;
37 type LoadCached<'a>
38 = &'a A
39 where
40 Self::Arc: 'a;
41 #[inline]
42 fn load_owned(&self) -> Self::Owned {
43 self.load_owned()
44 }
45 #[inline(always)]
46 fn load_cached<'a>(&self, cached: &'a mut Self::Owned) -> Self::LoadCached<'a> {
47 self.load_cached(cached)
48 }
49}
50
51impl<A: NonNullArcPtr, D: Domain, W: WritePolicy> AtomicArcRef for AtomicOptionArcPtr<A, D, W> {
52 type Arc = A;
53 type Owned = Option<A>;
54 type LoadCached<'a>
55 = Option<&'a A>
56 where
57 Self::Arc: 'a;
58 #[inline]
59 fn load_owned(&self) -> Self::Owned {
60 self.load_owned()
61 }
62 #[inline(always)]
63 fn load_cached<'a>(&self, cached: &'a mut Self::Owned) -> Self::LoadCached<'a> {
64 self.load_cached(cached)
65 }
66}
67
68impl<T: Deref> AtomicArcRef for T
69where
70 T::Target: AtomicArcRef,
71{
72 type Arc = <T::Target as AtomicArcRef>::Arc;
73 type Owned = <T::Target as AtomicArcRef>::Owned;
74 type LoadCached<'a>
75 = <T::Target as AtomicArcRef>::LoadCached<'a>
76 where
77 Self::Arc: 'a;
78 #[inline]
79 fn load_owned(&self) -> Self::Owned {
80 (**self).load_owned()
81 }
82 #[inline]
83 fn load_cached<'a>(&self, cached: &'a mut Self::Owned) -> Self::LoadCached<'a> {
84 (**self).load_cached(cached)
85 }
86}
87
88#[derive(Debug, Clone)]
118pub struct Cache<A: AtomicArcRef> {
119 inner: A,
120 cached: A::Owned,
121}
122
123impl<A: AtomicArcRef> Cache<A> {
124 #[inline]
126 pub fn new(inner: A) -> Self {
127 let cached = inner.load_owned();
128 Self { inner, cached }
129 }
130
131 pub fn inner(&self) -> &A {
133 &self.inner
134 }
135
136 pub fn into_inner(self) -> A {
138 self.inner
139 }
140
141 #[inline]
143 pub fn load(&mut self) -> A::LoadCached<'_> {
144 self.inner.load_cached(&mut self.cached)
145 }
146}
147
148impl<A: AtomicArcRef> From<A> for Cache<A> {
149 fn from(value: A) -> Self {
150 Self::new(value)
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use alloc::sync::Arc;
157
158 use crate::{domain, AtomicArc, AtomicOptionArc, Cache};
159
160 #[test]
161 fn cache() {
162 domain!(TestDomain(1));
163 let atomic_arc = Arc::new(AtomicArc::<usize, TestDomain>::from(0));
164 let mut cache = Cache::new(atomic_arc);
165 assert_eq!(**cache.load(), 0);
166 cache.inner().store(1.into());
167 assert_eq!(**cache.load(), 1);
168 assert_eq!(*cache.cached, 1);
169 }
170
171 #[test]
172 fn cache_option() {
173 domain!(TestDomain(1));
174 let atomic_arc = Arc::new(AtomicOptionArc::<usize, TestDomain>::from(0));
175 let mut cache = Cache::new(atomic_arc);
176 assert_eq!(**cache.load().unwrap(), 0);
177 cache.inner().store(None);
178 assert!(cache.load().is_none());
179 assert_eq!(cache.cached, None);
180 }
181}