1use std::sync::atomic::AtomicUsize;
4use std::sync::atomic::Ordering as AtomicOrdering;
5use std::sync::Arc;
6use std::sync::Weak;
7
8use parking_lot::Mutex;
9use parking_lot::Once;
10use parking_lot::OnceState;
11use parking_lot::RwLock;
12
13pub(crate) struct RawQrwCell<T> {
15 inner: [RwLock<Option<Arc<T>>>; 2],
16 selector: AtomicUsize,
17 update_lock: Mutex<()>,
18 init: Once,
19}
20
21impl<T: Default> Default for RawQrwCell<T> {
22 fn default() -> Self {
23 let init = Once::new();
24 init.call_once(|| ());
25 Self {
26 inner: [RwLock::new(Some(Arc::new(T::default()))), RwLock::new(None)],
27 selector: AtomicUsize::new(0),
28 update_lock: Mutex::new(()),
29 init,
30 }
31 }
32}
33
34impl<T> RawQrwCell<T> {
35 pub(crate) const fn new() -> Self {
37 Self {
38 inner: [
39 parking_lot::const_rwlock(None),
40 parking_lot::const_rwlock(None),
41 ],
42 selector: AtomicUsize::new(0),
43 update_lock: parking_lot::const_mutex(()),
44 init: Once::new(),
45 }
46 }
47
48 pub(crate) fn with_value(value: T) -> Self {
50 let init = Once::new();
51 init.call_once(|| ());
52 Self {
53 inner: [RwLock::new(Some(Arc::new(value))), RwLock::new(None)],
54 selector: AtomicUsize::new(0),
55 update_lock: Mutex::new(()),
56 init,
57 }
58 }
59
60 pub(crate) fn get(&self) -> Arc<T> {
62 if self.init.state() != OnceState::Done {
63 panic!("Attempted to read from a qrwcell that has not been initialized!");
64 }
65 loop {
66 let selector = self.get_selector();
67 let guard = self.inner[selector].read();
68 if let Some(value) = guard.as_ref() {
69 break Arc::clone(value);
70 }
71 }
72 }
73
74 pub(crate) fn get_weak(&self) -> Weak<T> {
76 if self.init.state() != OnceState::Done {
77 panic!("Attempted to read from a qrwcell that has not been initialized!");
78 }
79 loop {
80 let selector = self.get_selector();
81 let guard = self.inner[selector].read();
82 if let Some(value) = guard.as_ref() {
83 break Arc::downgrade(value);
84 }
85 }
86 }
87
88 pub(crate) fn update(&self, new: T) -> Arc<T> {
90 self.init.call_once(|| ());
91 let _update_lock = self.update_lock.lock();
92 let new_arc = Arc::new(new);
93 let selector = self.get_selector() ^ 1;
94 {
95 let mut cell = self.inner[selector].write();
96 *cell = Some(Arc::clone(&new_arc));
97 }
98 let selector = self.switch_selector();
99 {
100 let mut cell = self.inner[selector].write();
101 cell.take().unwrap_or(new_arc)
102 }
103 }
104
105 #[inline]
106 fn get_selector(&self) -> usize {
107 self.selector.load(AtomicOrdering::Acquire)
108 }
109
110 #[inline]
111 fn switch_selector(&self) -> usize {
112 self.selector.fetch_xor(1, AtomicOrdering::Release)
113 }
114}