orx_pinned_vec/concurrent_pinned_vec.rs
1use crate::{PinnedVec, PinnedVecGrowthError};
2use core::ops::{Range, RangeBounds};
3
4/// A wrapper for a pinned vector which provides additional guarantees for concurrent programs.
5///
6/// Note that a concurrent pinned vec inherits pinned memory location guarantees.
7///
8/// The struct encapsulates many methods of the pinned vector which are not suitable for concurrent programs.
9/// Further, it exposes new and mostly unsafe methods for allowing performant concurrent collections.
10/// It is designed to be a core structure for concurrent collections with a safe api.
11pub trait ConcurrentPinnedVec<T> {
12 /// Type of the wrapped pinned vector.
13 type P: PinnedVec<T>;
14
15 /// Iterator yielding slices corresponding to a range of indices, returned by the `slice` method.
16 type SliceIter<'a>: IntoIterator<Item = &'a [T]> + Default
17 where
18 T: 'a,
19 Self: 'a;
20
21 /// Iterator yielding mutable slices corresponding to a range of indices, returned by the `slice_mut` and `slice_mut_unchecked` methods.
22 type SliceMutIter<'a>: IntoIterator<Item = &'a mut [T]> + Default
23 where
24 T: 'a,
25 Self: 'a;
26
27 /// Iterator yielding pointers to elements of the vector.
28 type PtrIter<'a>: ExactSizeIterator<Item = *mut T>
29 where
30 Self: 'a;
31
32 /// Converts back to the underlying pinned vector with the given length.
33 ///
34 /// # Safety
35 ///
36 /// This method is unsafe due to the following.
37 /// The concurrent pinned vector is the core data structure for different concurrent collections
38 /// which allow writing to the vector in different ways.
39 /// The wrapper is responsible to deal with the gaps.
40 ///
41 /// This method can safely be called if entries in all positions `0..len` are written.
42 unsafe fn into_inner(self, len: usize) -> Self::P;
43
44 /// Clones the concurrent pinned vector with for the first `len` elements.
45 /// The created concurrent vector will have the same capacity and maximum capacity as this collection;
46 /// however, only the values within 0..len will be cloned to the target.
47 ///
48 /// # Safety
49 ///
50 /// This method is unsafe due to the following.
51 /// The concurrent pinned vector is the core data structure for different concurrent collections
52 /// which allow writing to the vector in different ways.
53 /// The wrapper is responsible to deal with the gaps.
54 ///
55 /// This method can safely be called if entries in all positions `0..len` are written.
56 unsafe fn clone_with_len(&self, len: usize) -> Self
57 where
58 T: Clone;
59
60 // &self get
61
62 /// Returns an iterator over positions `0..len` of the vector.
63 ///
64 /// # Safety
65 ///
66 /// This method is unsafe since the concurrent pinned vector might contain gaps.
67 ///
68 /// This method can safely be called if entries in all positions `0..len` are written.
69 unsafe fn iter<'a>(&'a self, len: usize) -> impl Iterator<Item = &'a T> + 'a
70 where
71 T: 'a;
72
73 /// Returns an iterator over positions `range` of the vector.
74 ///
75 /// # Safety
76 ///
77 /// This method is unsafe since the concurrent pinned vector might contain gaps.
78 ///
79 /// This method can safely be called if entries in all positions `range` are written.
80 unsafe fn iter_over_range<'a, R: RangeBounds<usize>>(
81 &'a self,
82 range: R,
83 ) -> impl Iterator<Item = &'a T> + 'a
84 where
85 T: 'a;
86
87 /// Returns a reference to the element at the `index`-th position.
88 ///
89 /// # Safety
90 ///
91 /// This method is unsafe since the concurrent pinned vector might contain gaps.
92 ///
93 /// This method can safely be called if the entry at position `index` is written.
94 unsafe fn get(&self, index: usize) -> Option<&T>;
95
96 /// Returns a mutable reference to the element at the `index`-th position.
97 ///
98 /// # Safety
99 ///
100 /// This method is used to write to the vector.
101 /// Therefore, its position will initially be uninitialized; hence, reading the pointer might result in UB.
102 unsafe fn get_ptr_mut(&self, index: usize) -> *mut T;
103
104 /// Returns an iterator of mutable slices to the elements extending over positions `range` of the vector.
105 ///
106 /// # Safety
107 ///
108 /// This method is used to write to the vector.
109 /// Therefore, the positions will initially be uninitialized; hence, reading from the slices might result in UB.
110 unsafe fn slices_mut<R: RangeBounds<usize>>(&self, range: R) -> Self::SliceMutIter<'_>;
111
112 /// Returns an iterator of slices to the elements extending over positions `range` of the vector.
113 fn slices<R: RangeBounds<usize>>(&self, range: R) -> Self::SliceIter<'_>;
114
115 // capacity
116
117 /// Returns the maximum possible capacity that the vector can concurrently grow to without requiring a `&mut self` reference.
118 ///
119 /// In order to grow beyond this capacity, `reserve_maximum_concurrent_capacity` method can be used.
120 fn max_capacity(&self) -> usize;
121
122 /// Returns the current capacity of the vector, which is actually allocated.
123 fn capacity(&self) -> usize;
124
125 /// Tries to concurrently grow the capacity of the vector to at least `new_capacity`. Returns:
126 /// * Ok of the new capacity if succeeds
127 /// * Err otherwise.
128 ///
129 /// Behavior of this method is deterministic.
130 /// The method always succeeds (fails) if `new_capacity <= self.max_capacity()` (otherwise).
131 ///
132 /// If the method returns an error, `reserve_maximum_concurrent_capacity` method can be used; however, with a `&mut self` reference.
133 /// Then, `grow_to` will succeed.
134 fn grow_to(&self, new_capacity: usize) -> Result<usize, PinnedVecGrowthError>;
135
136 /// Tries to concurrently grow the capacity of the vector to at least `new_capacity`. Returns:
137 /// * Ok of the new capacity if succeeds
138 /// * Err otherwise.
139 ///
140 /// Behavior of this method is deterministic.
141 /// The method always succeeds (fails) if `new_capacity <= self.max_capacity()` (otherwise).
142 ///
143 /// If the method returns an error, `reserve_maximum_concurrent_capacity` method can be used;
144 /// however, with a `&mut self` reference.
145 /// Then, `grow_to` will succeed.
146 ///
147 /// During growth:
148 ///
149 /// * length of the vector is increased to its new capacity;
150 /// * the elements in the range `len..capacity` are filled with the values
151 /// obtained by repeatedly calling the function `fill_with`.
152 fn grow_to_and_fill_with<F>(
153 &self,
154 new_capacity: usize,
155 fill_with: F,
156 ) -> Result<usize, PinnedVecGrowthError>
157 where
158 F: Fn() -> T;
159
160 /// Fills the provided `range` with elements created by successively calling the `fill_with` function.
161 fn fill_with<F>(&self, range: Range<usize>, fill_with: F)
162 where
163 F: Fn() -> T;
164
165 /// Increases the `maximum_capacity` to the `new_maximum_capacity`.
166 ///
167 /// # Safety
168 ///
169 /// This method is unsafe since the concurrent pinned vector might contain gaps.
170 /// The vector must be gap-free while increasing the maximum capacity.
171 ///
172 /// This method can safely be called if entries in all positions `0..len` are written.
173 unsafe fn reserve_maximum_concurrent_capacity(
174 &mut self,
175 len: usize,
176 new_maximum_capacity: usize,
177 ) -> usize;
178
179 /// Increases the `maximum_capacity` to the `new_maximum_capacity`.
180 /// If capacity extension leads to allocation, allocated memory is filled with the given function.
181 ///
182 /// # Safety
183 ///
184 /// This method is unsafe since the concurrent pinned vector might contain gaps.
185 /// The vector must be gap-free while increasing the maximum capacity.
186 ///
187 /// This method can safely be called if entries in all positions `0..len` are written.
188 unsafe fn reserve_maximum_concurrent_capacity_fill_with<F>(
189 &mut self,
190 len: usize,
191 new_maximum_capacity: usize,
192 fill_with: F,
193 ) -> usize
194 where
195 F: Fn() -> T;
196
197 // &mut self
198
199 /// Sets the length of the underlying pinned vector to the given `len`.
200 ///
201 /// # Safety
202 ///
203 /// This method is unsafe since the concurrent pinned vector might contain gaps.
204 ///
205 /// This method can safely be called if entries in all positions `0..len` are written.
206 unsafe fn set_pinned_vec_len(&mut self, len: usize);
207
208 /// Returns a mutable iterator over positions `0..len` of the vector.
209 ///
210 /// # Safety
211 ///
212 /// This method is unsafe since the concurrent pinned vector might contain gaps.
213 ///
214 /// This method can safely be called if entries in all positions `0..len` are written.
215 unsafe fn iter_mut<'a>(&'a mut self, len: usize) -> impl Iterator<Item = &'a mut T> + 'a
216 where
217 T: 'a;
218
219 /// Returns a reference to the element at the `index`-th position.
220 ///
221 /// # Safety
222 ///
223 /// This method is unsafe since the concurrent pinned vector might contain gaps.
224 ///
225 /// This method can safely be called if the entry at position `index` is written.
226 unsafe fn get_mut(&mut self, index: usize) -> Option<&mut T>;
227
228 /// Clears the concurrent pinned vector.
229 ///
230 /// # Safety
231 ///
232 /// This method is unsafe since the concurrent pinned vector might contain gaps.
233 ///
234 /// This method can safely be called if entries in all positions `0..len` are written.
235 unsafe fn clear(&mut self, len: usize);
236
237 /// Returns an iterator yielding pointers to elements within the given `range`.
238 ///
239 /// # SAFETY
240 ///
241 /// The method is marked unsafe due to the possibility of `range` being out of bounds.
242 /// This method does not perform a bounds check and it leads to UB if the range is
243 /// out of bounds.
244 ///
245 /// Returned iterator is created from a shared reference to the vec.
246 /// Therefore, the vec, cannot be mutated while using the iterator.
247 ///
248 /// Further, since the iterator is created using a shared reference to the vec,
249 /// it cannot outlive the vec.
250 ///
251 /// These guarantee that all pointers that the iterator yields will be valid.
252 ///
253 /// In brief, it is safe to use this method provided that the caller guarantees
254 /// that the range is in bounds.
255 unsafe fn ptr_iter_unchecked(&self, range: Range<usize>) -> Self::PtrIter<'_>;
256}