fuchsia_rcu_collections/
rcu_array.rs1use fuchsia_rcu::{RcuCell, RcuReadScope};
6
7#[derive(Default, Debug)]
14pub struct RcuArray<T: Send + Sync + 'static> {
15 inner: RcuCell<Box<[T]>>,
16}
17
18impl<T: Send + Sync + 'static> RcuArray<T> {
19 pub fn get<'a>(&self, scope: &'a RcuReadScope, index: usize) -> Option<&'a T> {
22 let array = self.inner.as_ref(scope);
23 array.get(index)
24 }
25
26 pub fn as_slice<'a>(&self, scope: &'a RcuReadScope) -> &'a [T] {
28 let array = self.inner.as_ref(scope);
29 array.as_ref()
30 }
31
32 pub unsafe fn ensure_at_least(&self, requested_size: usize)
43 where
44 T: Clone + Default,
45 {
46 let array = self.inner.read();
47 if array.len() >= requested_size {
48 return;
49 }
50 let new_size = std::cmp::max(requested_size, array.len() * 2);
51 self.copy_update(&array, new_size);
52 }
53
54 pub fn update(&self, new_array: Vec<T>) {
56 self.inner.update(new_array.into_boxed_slice());
57 }
58
59 fn copy_update(&self, array: &[T], new_size: usize)
60 where
61 T: Clone + Default,
62 {
63 let mut new_array = Vec::new();
64 new_array.reserve_exact(new_size);
65 for item in array.iter() {
66 new_array.push(item.clone());
67 }
68 for _ in array.len()..new_size {
69 new_array.push(T::default());
70 }
71 self.inner.update(new_array.into_boxed_slice());
72 }
73}
74
75impl<T: Clone + Sync + Send + 'static> Clone for RcuArray<T> {
76 fn clone(&self) -> Self {
77 Self { inner: self.inner.clone() }
78 }
79}
80
81impl<T: Send + Sync + 'static> From<Vec<T>> for RcuArray<T> {
83 fn from(value: Vec<T>) -> Self {
84 Self { inner: RcuCell::new(value.into_boxed_slice()) }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use fuchsia_rcu::{RcuReadScope, rcu_synchronize};
92
93 #[test]
94 fn test_rcu_array_get() {
95 let array = RcuArray::from(vec![1, 2, 3]);
96 let scope = RcuReadScope::new();
97 assert_eq!(array.get(&scope, 0), Some(&1));
98 assert_eq!(array.get(&scope, 1), Some(&2));
99 assert_eq!(array.get(&scope, 2), Some(&3));
100 assert_eq!(array.get(&scope, 3), None);
101 }
102
103 #[test]
104 fn test_rcu_array_as_slice() {
105 let array = RcuArray::from(vec![1, 2, 3]);
106 let scope = RcuReadScope::new();
107 assert_eq!(array.as_slice(&scope), &[1, 2, 3]);
108 }
109
110 #[test]
111 fn test_rcu_array_ensure_at_least() {
112 let array = RcuArray::from(vec![1, 2, 3]);
113
114 unsafe { array.ensure_at_least(5) };
115 let scope = RcuReadScope::new();
116 assert_eq!(array.as_slice(&scope), &[1, 2, 3, 0, 0, 0]);
118
119 unsafe { array.ensure_at_least(2) };
120
121 assert_eq!(array.as_slice(&scope), &[1, 2, 3, 0, 0, 0]);
123
124 unsafe { array.ensure_at_least(12) };
125 assert_eq!(array.as_slice(&scope), &[1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
126
127 std::mem::drop(scope);
128 rcu_synchronize();
129 }
130
131 #[test]
132 fn test_rcu_array_from_vec() {
133 let vec = vec![1, 2, 3];
134 let array = RcuArray::from(vec.clone());
135 let scope = RcuReadScope::new();
136 assert_eq!(array.as_slice(&scope), vec.as_slice());
137 }
138}