use crate::{
GrowthWithConstantTimeAccess,
concurrent_pinned_vec::into_iter_ptr_slices::IntoIterPtrOfConSlices,
};
use alloc::vec::Vec;
use core::{cell::UnsafeCell, ops::Range};
pub struct ConcurrentSplitVecIntoIter<T, G>
where
G: GrowthWithConstantTimeAccess,
{
slices: IntoIterPtrOfConSlices<T, G>,
len_of_remaining_slices: usize,
current_ptr: *const T,
current_last: *const T,
}
impl<T, G> ConcurrentSplitVecIntoIter<T, G>
where
G: GrowthWithConstantTimeAccess,
{
pub fn new(
capacity: usize,
fragments: Vec<UnsafeCell<*mut T>>,
growth: G,
range: Range<usize>,
) -> Self {
let len_of_remaining_slices = range.len();
let slices = IntoIterPtrOfConSlices::new(capacity, fragments, growth, range);
Self {
slices,
len_of_remaining_slices,
current_ptr: core::ptr::null(),
current_last: core::ptr::null(),
}
}
fn remaining(&self) -> usize {
let remaining_current = match self.current_ptr.is_null() {
true => 0,
false => unsafe { self.current_last.offset_from(self.current_ptr) as usize + 1 },
};
self.len_of_remaining_slices + remaining_current
}
fn next_ptr(&mut self) -> Option<*mut T> {
match self.current_ptr {
ptr if ptr.is_null() => self.next_slice(),
ptr if ptr == self.current_last => {
self.current_ptr = core::ptr::null_mut();
Some(ptr as *mut T)
}
ptr => {
self.current_ptr = unsafe { self.current_ptr.add(1) };
Some(ptr as *mut T)
}
}
}
fn next_slice(&mut self) -> Option<*mut T> {
self.slices.next().and_then(|(ptr, len)| {
debug_assert!(len > 0);
self.len_of_remaining_slices -= len;
self.current_ptr = ptr;
self.current_last = unsafe { ptr.add(len - 1) };
self.next_ptr()
})
}
}
impl<T, G> Iterator for ConcurrentSplitVecIntoIter<T, G>
where
G: GrowthWithConstantTimeAccess,
{
type Item = T;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.next_ptr().map(|ptr| unsafe { ptr.read() })
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.remaining();
(len, Some(len))
}
}
impl<T, G> ExactSizeIterator for ConcurrentSplitVecIntoIter<T, G>
where
G: GrowthWithConstantTimeAccess,
{
fn len(&self) -> usize {
self.remaining()
}
}
impl<T, G> Drop for ConcurrentSplitVecIntoIter<T, G>
where
G: GrowthWithConstantTimeAccess,
{
fn drop(&mut self) {
if core::mem::needs_drop::<T>() {
while let Some(ptr) = self.next_ptr() {
unsafe { ptr.drop_in_place() };
}
}
}
}