len_caching_lock/
rwlock.rs1use std::ops::{Deref, DerefMut};
18use std::sync::atomic::AtomicUsize;
19use std::sync::atomic::Ordering;
20
21use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
22
23use Len;
24
25#[derive(Debug)]
29pub struct LenCachingRwLock<T: ?Sized> {
30 len: AtomicUsize,
31 data: RwLock<T>,
32}
33
34impl<T: Len + Default> Default for LenCachingRwLock<T> {
35 fn default() -> Self {
36 LenCachingRwLock::new(T::default())
37 }
38}
39
40impl<T: Len> From<T> for LenCachingRwLock<T> {
41 fn from(data: T) -> Self {
42 LenCachingRwLock::new(data)
43 }
44}
45
46impl<T: Len> LenCachingRwLock<T> {
47 pub fn new(data: T) -> Self {
49 LenCachingRwLock {
50 len: AtomicUsize::new(data.len()),
51 data: RwLock::new(data),
52 }
53 }
54}
55
56impl<T: Len + ?Sized> LenCachingRwLock<T> {
57 pub fn load_len(&self) -> usize {
60 self.len.load(Ordering::SeqCst)
61 }
62
63 pub fn write(&self) -> CachingRwLockWriteGuard<T> {
66 CachingRwLockWriteGuard {
67 write_guard: self.data.write(),
68 len: &self.len,
69 }
70 }
71
72 pub fn try_write(&self) -> Option<CachingRwLockWriteGuard<T>> {
75 Some(CachingRwLockWriteGuard {
76 write_guard: self.data.try_write()?,
77 len: &self.len,
78 })
79 }
80
81 pub fn read(&self) -> RwLockReadGuard<T> {
84 self.data.read()
85 }
86
87 pub fn try_read(&self) -> Option<RwLockReadGuard<T>> {
90 self.data.try_read()
91 }
92}
93
94pub struct CachingRwLockWriteGuard<'a, T: Len + 'a + ?Sized> {
96 write_guard: RwLockWriteGuard<'a, T>,
97 len: &'a AtomicUsize,
98}
99
100impl<'a, T: Len + ?Sized> CachingRwLockWriteGuard<'a, T> {
101 pub fn inner_mut(&mut self) -> &mut RwLockWriteGuard<'a, T> {
104 &mut self.write_guard
105 }
106
107 pub fn inner(&self) -> &RwLockWriteGuard<'a, T> {
110 &self.write_guard
111 }
112}
113
114impl<'a, T: Len + ?Sized> Drop for CachingRwLockWriteGuard<'a, T> {
115 fn drop(&mut self) {
116 self.len.store(self.write_guard.len(), Ordering::SeqCst);
117 }
118}
119
120impl<'a, T: Len + ?Sized> Deref for CachingRwLockWriteGuard<'a, T> {
121 type Target = T;
122 fn deref(&self) -> &T {
123 self.write_guard.deref()
124 }
125}
126
127impl<'a, T: Len + ?Sized> DerefMut for CachingRwLockWriteGuard<'a, T> {
128 fn deref_mut(&mut self) -> &mut T {
129 self.write_guard.deref_mut()
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use std::collections::VecDeque;
137
138 #[test]
139 fn caches_len() {
140 let v = vec![1,2,3];
141 let lcl = LenCachingRwLock::new(v);
142 assert_eq!(lcl.load_len(), 3);
143 lcl.write().push(4);
144 assert_eq!(lcl.load_len(), 4);
145 }
146
147 #[test]
148 fn works_with_vec() {
149 let v: Vec<i32> = Vec::new();
150 let lcl = LenCachingRwLock::new(v);
151 assert!(lcl.write().is_empty());
152 }
153
154 #[test]
155 fn works_with_vecdeque() {
156 let v: VecDeque<i32> = VecDeque::new();
157 let lcl = LenCachingRwLock::new(v);
158 lcl.write().push_front(4);
159 assert_eq!(lcl.load_len(), 1);
160 }
161
162 #[test]
163 fn read_works() {
164 let v = vec![1,2,3];
165 let lcl = LenCachingRwLock::new(v);
166 assert_eq!(lcl.read().len(), 3);
167 }
168}