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}