Skip to main content

orx_concurrent_vec/
exclusive.rs

1use crate::{ConcurrentVec, elem::ConcurrentElement};
2use core::sync::atomic::Ordering;
3use orx_pinned_vec::IntoConcurrentPinnedVec;
4
5impl<T, P> ConcurrentVec<T, P>
6where
7    P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
8{
9    /// Clears the concurrent bag.
10    pub fn clear(&mut self) {
11        unsafe { self.core.clear(self.core.state().len()) };
12    }
13
14    /// Removes the last element from the vector and returns it, or `None` if it is empty.
15    ///
16    /// # Examples
17    ///
18    /// ```rust
19    /// use orx_concurrent_vec::*;
20    ///
21    /// let mut vec = ConcurrentVec::new();
22    /// vec.push('a');
23    /// vec.push('b');
24    ///
25    /// assert_eq!(vec.pop(), Some('b'));
26    /// assert_eq!(vec.pop(), Some('a'));
27    /// assert_eq!(vec.pop(), None);
28    /// ```
29    pub fn pop(&mut self) -> Option<T> {
30        let len = self.len();
31        match len {
32            0 => None,
33            n => {
34                let last_idx = n - 1;
35                // SAFETY: the element exists and we have &mut reference to vec
36                let elem = unsafe { self.core.get_mut(last_idx) }?;
37                let value = elem.0.exclusive_take();
38
39                self.len_written().store(last_idx, Ordering::Relaxed);
40                self.len_reserved().store(last_idx, Ordering::Relaxed);
41
42                value
43            }
44        }
45    }
46
47    /// Note that [`ConcurrentVec::maximum_capacity`] returns the maximum possible number of elements that the underlying pinned vector can grow to without reserving maximum capacity.
48    ///
49    /// In other words, the pinned vector can automatically grow up to the [`ConcurrentVec::maximum_capacity`] with `write` and `write_n_items` methods, using only a shared reference.
50    ///
51    /// When required, this maximum capacity can be attempted to increase by this method with a mutable reference.
52    ///
53    /// Importantly note that maximum capacity does not correspond to the allocated memory.
54    ///
55    /// Among the common pinned vector implementations:
56    /// * `SplitVec<_, Doubling>`: supports this method; however, it does not require for any practical size.
57    /// * `SplitVec<_, Linear>`: is guaranteed to succeed and increase its maximum capacity to the required value.
58    /// * `FixedVec<_>`: is the most strict pinned vector which cannot grow even in a single-threaded setting. Currently, it will always return an error to this call.
59    ///
60    /// # Safety
61    /// This method is unsafe since the concurrent pinned vector might contain gaps. The vector must be gap-free while increasing the maximum capacity.
62    ///
63    /// This method can safely be called if entries in all positions 0..len are written.
64    pub fn reserve_maximum_capacity(&mut self, new_maximum_capacity: usize) -> usize {
65        unsafe {
66            self.core
67                .reserve_maximum_capacity(self.core.state().len(), new_maximum_capacity)
68        }
69    }
70}