From 936f355fb646e96e67160a6d48e06a9cc5d715e7 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 20:49:41 +0200 Subject: [PATCH 01/27] upgrade pinned vec version --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d8aa19b..defd9cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,8 @@ categories = ["data-structures", "rust-patterns", "no-std"] [dependencies] orx-iterable = { version = "1.3.0", default-features = false } orx-pseudo-default = { version = "2.1.0", default-features = false } -orx-pinned-vec = { version = "3.18.0", default-features = false } +# orx-pinned-vec = { version = "3.18.0", default-features = false } +orx-pinned-vec = { git = "https://github.com/orxfun/orx-pinned-vec", branch = "into-iter-for-concurrent-pinned-vectors" } orx-concurrent-iter = { version = "3.1.0", default-features = false } [[bench]] From 9dd03d829ebdaee802b9e297aa711705ee03d7e7 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 20:52:18 +0200 Subject: [PATCH 02/27] convec into-iter placeholders --- src/concurrent_pinned_vec/con_pinvec.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/concurrent_pinned_vec/con_pinvec.rs b/src/concurrent_pinned_vec/con_pinvec.rs index 4e31272..83a4b51 100644 --- a/src/concurrent_pinned_vec/con_pinvec.rs +++ b/src/concurrent_pinned_vec/con_pinvec.rs @@ -195,6 +195,8 @@ impl ConcurrentPinnedVec for ConcurrentSp where Self: 'a; + type IntoIter = core::iter::Empty; + unsafe fn into_inner(mut self, len: usize) -> Self::P { let mut fragments = Vec::with_capacity(self.max_num_fragments); let mut take_fragment = |fragment| fragments.push(fragment); @@ -434,4 +436,8 @@ impl ConcurrentPinnedVec for ConcurrentSp unsafe fn ptr_iter_unchecked(&self, range: Range) -> Self::PtrIter<'_> { IterPtrOfCon::new(self.capacity(), &self.data, self.growth.clone(), range) } + + unsafe fn into_iter(self, range: Range) -> Self::IntoIter { + todo!() + } } From 1306e4bd303b1ed527559cf6c2f1db6facfda5fc Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 20:57:41 +0200 Subject: [PATCH 03/27] IntoIterPtrOfConSlices --- src/concurrent_pinned_vec/into_iter.rs | 6 + .../into_iter_ptr_slices.rs | 158 ++++++++++++++++++ src/concurrent_pinned_vec/mod.rs | 2 + 3 files changed, 166 insertions(+) create mode 100644 src/concurrent_pinned_vec/into_iter.rs create mode 100644 src/concurrent_pinned_vec/into_iter_ptr_slices.rs diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs new file mode 100644 index 0000000..1503729 --- /dev/null +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -0,0 +1,6 @@ +use alloc::vec::Vec; +use core::cell::UnsafeCell; + +pub struct ConcurrentSplitVecIntoIter { + data: Vec>, +} diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs new file mode 100644 index 0000000..f432bfb --- /dev/null +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -0,0 +1,158 @@ +use crate::{ + GrowthWithConstantTimeAccess, + range_helpers::{range_end, range_start}, +}; +use alloc::vec::Vec; +use core::cmp::min; +use core::{cell::UnsafeCell, iter::FusedIterator, ops::Range}; + +pub struct IntoIterPtrOfConSlices +where + G: GrowthWithConstantTimeAccess, +{ + fragments: Vec>, + growth: G, + sf: usize, + si: usize, + si_end: usize, + ef: usize, + ei: usize, + f: usize, +} + +impl IntoIterPtrOfConSlices +where + G: GrowthWithConstantTimeAccess, +{ + fn empty() -> Self { + Self { + fragments: Default::default(), + growth: G::pseudo_default(), + sf: 0, + si: 0, + si_end: 0, + ef: 0, + ei: 0, + f: 1, + } + } + + fn single_slice( + fragments: Vec>, + growth: G, + f: usize, + begin: usize, + end: usize, + ) -> Self { + Self { + fragments, + growth, + sf: f, + si: begin, + si_end: end, + ef: f, + ei: 0, + f, + } + } + + pub fn new( + capacity: usize, + fragments: Vec>, + growth: G, + range: Range, + ) -> Self { + let fragment_and_inner_indices = |i| growth.get_fragment_and_inner_indices_unchecked(i); + + let a = range_start(&range); + let b = min(capacity, range_end(&range, capacity)); + + match b.saturating_sub(a) { + 0 => Self::empty(), + _ => { + let (sf, si) = fragment_and_inner_indices(a); + let (ef, ei) = fragment_and_inner_indices(b - 1); + + match sf == ef { + true => Self::single_slice(fragments, growth, sf, si, ei + 1), + false => { + let si_end = growth.fragment_capacity_of(sf); + Self { + fragments, + growth, + sf, + si, + si_end, + ef, + ei, + f: sf, + } + } + } + } + } + } + + #[inline(always)] + fn remaining_len(&self) -> usize { + (1 + self.ef).saturating_sub(self.f) + } + + #[inline(always)] + fn get_ptr_fi(&self, f: usize, i: usize) -> *mut T { + let p = unsafe { *self.fragments[f].get() }; + unsafe { p.add(i) } + } + + #[inline(always)] + fn capacity_of(&self, f: usize) -> usize { + self.growth.fragment_capacity_of(f) + } +} + +impl Iterator for IntoIterPtrOfConSlices +where + G: GrowthWithConstantTimeAccess, +{ + type Item = (*mut T, usize); + + fn next(&mut self) -> Option { + match self.f { + f if f == self.sf => { + self.f += 1; + let len = self.si_end - self.si; + let p = self.get_ptr_fi(self.sf, self.si); + Some((p, len)) + } + f if f < self.ef => { + self.f += 1; + let len = self.capacity_of(f); + let p = self.get_ptr_fi(f, 0); + Some((p, len)) + } + f if f == self.ef => { + self.f += 1; + let len = self.ei + 1; + let p = self.get_ptr_fi(self.ef, 0); + Some((p, len)) + } + _ => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.remaining_len(); + (len, Some(len)) + } +} + +impl FusedIterator for IntoIterPtrOfConSlices where G: GrowthWithConstantTimeAccess {} + +impl ExactSizeIterator for IntoIterPtrOfConSlices +where + G: GrowthWithConstantTimeAccess, +{ + fn len(&self) -> usize { + self.remaining_len() + } +} diff --git a/src/concurrent_pinned_vec/mod.rs b/src/concurrent_pinned_vec/mod.rs index 134f191..361e541 100644 --- a/src/concurrent_pinned_vec/mod.rs +++ b/src/concurrent_pinned_vec/mod.rs @@ -1,4 +1,6 @@ mod con_pinvec; +mod into_iter; +mod into_iter_ptr_slices; mod iter_ptr; mod iter_ptr_slices; From 897ef02187a323e4bf6596a479dcd466186ac70e Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 20:58:59 +0200 Subject: [PATCH 04/27] ConcurrentSplitVecIntoIter is defined --- src/concurrent_pinned_vec/into_iter.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 1503729..5b623a4 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -1,6 +1,16 @@ +use crate::{ + GrowthWithConstantTimeAccess, + concurrent_pinned_vec::into_iter_ptr_slices::IntoIterPtrOfConSlices, +}; use alloc::vec::Vec; use core::cell::UnsafeCell; -pub struct ConcurrentSplitVecIntoIter { - data: Vec>, +pub struct ConcurrentSplitVecIntoIter +where + G: GrowthWithConstantTimeAccess, +{ + slices: IntoIterPtrOfConSlices, + len_of_remaining_slices: usize, + current_ptr: *const T, + current_last: *const T, } From 618c73dc66efc9a0216d8cac3cb5571e8127f06e Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:00:38 +0200 Subject: [PATCH 05/27] impl iterator for ConcurrentSplitVecIntoIter --- src/concurrent_pinned_vec/into_iter.rs | 84 +++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 5b623a4..aa43dea 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -3,7 +3,7 @@ use crate::{ concurrent_pinned_vec::into_iter_ptr_slices::IntoIterPtrOfConSlices, }; use alloc::vec::Vec; -use core::cell::UnsafeCell; +use core::{cell::UnsafeCell, ops::Range}; pub struct ConcurrentSplitVecIntoIter where @@ -14,3 +14,85 @@ where current_ptr: *const T, current_last: *const T, } + +impl<'a, T, G> ConcurrentSplitVecIntoIter +where + G: GrowthWithConstantTimeAccess, +{ + pub fn new( + capacity: usize, + fragments: Vec>, + growth: G, + range: Range, + ) -> 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, + // SAFETY: whenever current_ptr is not null, we know that current_last is also not + // null which is >= current_ptr. + false => unsafe { self.current_last.offset_from(self.current_ptr) as usize + 1 }, + }; + + self.len_of_remaining_slices + remaining_current + } + + 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; + // SAFETY: pointers are not null since slice is not empty + self.current_ptr = ptr; + self.current_last = unsafe { ptr.add(len - 1) }; + self.next() + }) + } +} + +impl Iterator for ConcurrentSplitVecIntoIter +where + G: GrowthWithConstantTimeAccess, +{ + type Item = *mut T; + + fn next(&mut self) -> Option { + 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 => { + // SAFETY: current_ptr is not the last element, hance current_ptr+1 is in bounds + self.current_ptr = unsafe { self.current_ptr.add(1) }; + + // SAFETY: ptr is valid and its value can be taken. + // Drop will skip this position which is now uninitialized. + Some(ptr as *mut T) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.remaining(); + (len, Some(len)) + } +} + +impl ExactSizeIterator for ConcurrentSplitVecIntoIter +where + G: GrowthWithConstantTimeAccess, +{ + fn len(&self) -> usize { + self.remaining() + } +} From 661cfd0df7ca2d4daf5dfdf9f2696edd26296d5c Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:02:10 +0200 Subject: [PATCH 06/27] ConcurrentSplitVecIntoIter yields read elements rather than pointer --- src/concurrent_pinned_vec/into_iter.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index aa43dea..2bdc77d 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -46,7 +46,7 @@ where self.len_of_remaining_slices + remaining_current } - fn next_slice(&mut self) -> Option<*mut T> { + fn next_slice(&mut self) -> Option { self.slices.next().and_then(|(ptr, len)| { debug_assert!(len > 0); self.len_of_remaining_slices -= len; @@ -62,14 +62,14 @@ impl Iterator for ConcurrentSplitVecIntoIter where G: GrowthWithConstantTimeAccess, { - type Item = *mut T; + type Item = T; fn next(&mut self) -> Option { 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) + Some(unsafe { ptr.read() }) } ptr => { // SAFETY: current_ptr is not the last element, hance current_ptr+1 is in bounds @@ -77,7 +77,7 @@ where // SAFETY: ptr is valid and its value can be taken. // Drop will skip this position which is now uninitialized. - Some(ptr as *mut T) + Some(unsafe { ptr.read() }) } } } From 9d1381665d2eeb64d0cb1ccb9cb34bb516530ff1 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:04:06 +0200 Subject: [PATCH 07/27] ConcurrentSplitVecIntoIter is wired up with con pin vec --- src/concurrent_pinned_vec/con_pinvec.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/concurrent_pinned_vec/con_pinvec.rs b/src/concurrent_pinned_vec/con_pinvec.rs index 83a4b51..31a03af 100644 --- a/src/concurrent_pinned_vec/con_pinvec.rs +++ b/src/concurrent_pinned_vec/con_pinvec.rs @@ -1,7 +1,7 @@ use crate::{ Doubling, Fragment, GrowthWithConstantTimeAccess, SplitVec, common_traits::iterator::{IterOfSlicesOfCon, SliceBorrowAsMut, SliceBorrowAsRef}, - concurrent_pinned_vec::iter_ptr::IterPtrOfCon, + concurrent_pinned_vec::{into_iter::ConcurrentSplitVecIntoIter, iter_ptr::IterPtrOfCon}, fragment::transformations::{fragment_from_raw, fragment_into_raw}, }; use alloc::vec::Vec; @@ -195,7 +195,7 @@ impl ConcurrentPinnedVec for ConcurrentSp where Self: 'a; - type IntoIter = core::iter::Empty; + type IntoIter = ConcurrentSplitVecIntoIter; unsafe fn into_inner(mut self, len: usize) -> Self::P { let mut fragments = Vec::with_capacity(self.max_num_fragments); @@ -437,7 +437,9 @@ impl ConcurrentPinnedVec for ConcurrentSp IterPtrOfCon::new(self.capacity(), &self.data, self.growth.clone(), range) } - unsafe fn into_iter(self, range: Range) -> Self::IntoIter { - todo!() + unsafe fn into_iter(mut self, range: Range) -> Self::IntoIter { + let mut data = Vec::new(); + core::mem::swap(&mut self.data, &mut data); + ConcurrentSplitVecIntoIter::new(self.capacity(), data, self.growth.clone(), range) } } From db84e11736f3aac4362d62ef00d855c05ed679cb Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:07:31 +0200 Subject: [PATCH 08/27] refactor ConcurrentSplitVecIntoIter --- src/concurrent_pinned_vec/into_iter.rs | 50 +++++++++++++++++--------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 2bdc77d..31772dc 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -46,14 +46,32 @@ where self.len_of_remaining_slices + remaining_current } - fn next_slice(&mut self) -> Option { + 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 => { + // SAFETY: current_ptr is not the last element, hance current_ptr+1 is in bounds + self.current_ptr = unsafe { self.current_ptr.add(1) }; + + // SAFETY: ptr is valid and its value can be taken. + // Drop will skip this position which is now uninitialized. + 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; // SAFETY: pointers are not null since slice is not empty self.current_ptr = ptr; self.current_last = unsafe { ptr.add(len - 1) }; - self.next() + self.next_ptr() }) } } @@ -64,22 +82,9 @@ where { type Item = T; + #[inline(always)] fn next(&mut self) -> Option { - 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(unsafe { ptr.read() }) - } - ptr => { - // SAFETY: current_ptr is not the last element, hance current_ptr+1 is in bounds - self.current_ptr = unsafe { self.current_ptr.add(1) }; - - // SAFETY: ptr is valid and its value can be taken. - // Drop will skip this position which is now uninitialized. - Some(unsafe { ptr.read() }) - } - } + self.next_ptr().map(|ptr| unsafe { ptr.read() }) } fn size_hint(&self) -> (usize, Option) { @@ -96,3 +101,14 @@ where self.remaining() } } + +impl Drop for ConcurrentSplitVecIntoIter +where + G: GrowthWithConstantTimeAccess, +{ + fn drop(&mut self) { + if core::mem::needs_drop::() { + while let Some(_) = self.next() {} + } + } +} From 03568937a68698687990473cd7c7d1300d057a81 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:08:31 +0200 Subject: [PATCH 09/27] revise drop to drop in place --- src/concurrent_pinned_vec/into_iter.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 31772dc..27ba443 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -108,7 +108,10 @@ where { fn drop(&mut self) { if core::mem::needs_drop::() { - while let Some(_) = self.next() {} + while let Some(ptr) = self.next_ptr() { + // SAFETY: ptr is in bounds and have not been dropped yet + unsafe { ptr.drop_in_place() }; + } } } } From bf0588cddf7be110690c433f0f42a63da499ee1c Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:18:45 +0200 Subject: [PATCH 10/27] drop is implemented for IntoIterPtrOfConSlices --- src/concurrent_pinned_vec/con_pinvec.rs | 8 +++---- .../into_iter_ptr_slices.rs | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/concurrent_pinned_vec/con_pinvec.rs b/src/concurrent_pinned_vec/con_pinvec.rs index 31a03af..851d5af 100644 --- a/src/concurrent_pinned_vec/con_pinvec.rs +++ b/src/concurrent_pinned_vec/con_pinvec.rs @@ -10,10 +10,10 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use core::{cell::UnsafeCell, ops::Range}; use orx_pinned_vec::ConcurrentPinnedVec; -struct FragmentData { - f: usize, - len: usize, - capacity: usize, +pub struct FragmentData { + pub f: usize, + pub len: usize, + pub capacity: usize, } /// Concurrent wrapper ([`orx_pinned_vec::ConcurrentPinnedVec`]) for the `SplitVec`. diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs index f432bfb..3a09fb0 100644 --- a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -1,5 +1,6 @@ use crate::{ - GrowthWithConstantTimeAccess, + Fragment, GrowthWithConstantTimeAccess, + fragment::transformations::fragment_from_raw, range_helpers::{range_end, range_start}, }; use alloc::vec::Vec; @@ -20,6 +21,24 @@ where f: usize, } +impl Drop for IntoIterPtrOfConSlices +where + G: GrowthWithConstantTimeAccess, +{ + fn drop(&mut self) { + for f in 0..self.fragments.len() { + let ptr = unsafe { *self.fragments[f].get() }; + match ptr.is_null() { + true => break, + false => { + let capacity = self.capacity_of(f); + let _fragment_to_drop = unsafe { fragment_from_raw(ptr, 0, capacity) }; + } + } + } + } +} + impl IntoIterPtrOfConSlices where G: GrowthWithConstantTimeAccess, From 2b83beba0c77b8ff6a0dc2b0ff7cdbb7bb966655 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:18:58 +0200 Subject: [PATCH 11/27] IntoIterPtrOfConSlices is made private --- src/concurrent_pinned_vec/into_iter_ptr_slices.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs index 3a09fb0..842544e 100644 --- a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -7,7 +7,7 @@ use alloc::vec::Vec; use core::cmp::min; use core::{cell::UnsafeCell, iter::FusedIterator, ops::Range}; -pub struct IntoIterPtrOfConSlices +pub(super) struct IntoIterPtrOfConSlices where G: GrowthWithConstantTimeAccess, { From 561db8f05b6df39a314dbd69095cc6f2715c3530 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:19:41 +0200 Subject: [PATCH 12/27] test modules cor con-pin-vec --- src/concurrent_pinned_vec/into_iter_ptr_slices.rs | 2 +- src/concurrent_pinned_vec/mod.rs | 3 +++ src/concurrent_pinned_vec/tests/into_iter.rs | 1 + src/concurrent_pinned_vec/tests/mod.rs | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/concurrent_pinned_vec/tests/into_iter.rs create mode 100644 src/concurrent_pinned_vec/tests/mod.rs diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs index 842544e..c2a7821 100644 --- a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -1,5 +1,5 @@ use crate::{ - Fragment, GrowthWithConstantTimeAccess, + GrowthWithConstantTimeAccess, fragment::transformations::fragment_from_raw, range_helpers::{range_end, range_start}, }; diff --git a/src/concurrent_pinned_vec/mod.rs b/src/concurrent_pinned_vec/mod.rs index 361e541..da01639 100644 --- a/src/concurrent_pinned_vec/mod.rs +++ b/src/concurrent_pinned_vec/mod.rs @@ -1,3 +1,6 @@ +#[cfg(test)] +mod tests; + mod con_pinvec; mod into_iter; mod into_iter_ptr_slices; diff --git a/src/concurrent_pinned_vec/tests/into_iter.rs b/src/concurrent_pinned_vec/tests/into_iter.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/concurrent_pinned_vec/tests/into_iter.rs @@ -0,0 +1 @@ + diff --git a/src/concurrent_pinned_vec/tests/mod.rs b/src/concurrent_pinned_vec/tests/mod.rs new file mode 100644 index 0000000..505e27f --- /dev/null +++ b/src/concurrent_pinned_vec/tests/mod.rs @@ -0,0 +1 @@ +mod into_iter; From 85f7a745b72581eb14083ebbd8c6e764d8082783 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:26:23 +0200 Subject: [PATCH 13/27] define destruct --- src/concurrent_pinned_vec/con_pinvec.rs | 17 ++++++++++---- src/concurrent_pinned_vec/tests/into_iter.rs | 24 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/concurrent_pinned_vec/con_pinvec.rs b/src/concurrent_pinned_vec/con_pinvec.rs index 851d5af..47cc3ff 100644 --- a/src/concurrent_pinned_vec/con_pinvec.rs +++ b/src/concurrent_pinned_vec/con_pinvec.rs @@ -35,6 +35,16 @@ impl Drop for ConcurrentSplitVec { } impl ConcurrentSplitVec { + pub(super) fn destruct(mut self) -> (G, Vec>, usize) { + let mut data = Vec::new(); + core::mem::swap(&mut self.data, &mut data); + ( + self.growth.clone(), + data, + self.capacity.load(Ordering::Relaxed), + ) + } + unsafe fn get_raw_mut_unchecked_fi(&self, f: usize, i: usize) -> *mut T { let p = unsafe { *self.data[f].get() }; unsafe { p.add(i) } @@ -437,9 +447,8 @@ impl ConcurrentPinnedVec for ConcurrentSp IterPtrOfCon::new(self.capacity(), &self.data, self.growth.clone(), range) } - unsafe fn into_iter(mut self, range: Range) -> Self::IntoIter { - let mut data = Vec::new(); - core::mem::swap(&mut self.data, &mut data); - ConcurrentSplitVecIntoIter::new(self.capacity(), data, self.growth.clone(), range) + unsafe fn into_iter(self, range: Range) -> Self::IntoIter { + let (growth, data, capacity) = self.destruct(); + ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) } } diff --git a/src/concurrent_pinned_vec/tests/into_iter.rs b/src/concurrent_pinned_vec/tests/into_iter.rs index 8b13789..92e7c82 100644 --- a/src/concurrent_pinned_vec/tests/into_iter.rs +++ b/src/concurrent_pinned_vec/tests/into_iter.rs @@ -1 +1,25 @@ +use crate::{Doubling, SplitVec}; +use orx_pinned_vec::{IntoConcurrentPinnedVec, PinnedVec}; +use std::string::ToString; +#[test] +fn into_iter_non_taken() { + let iter = || { + let vec: SplitVec<_, Doubling> = (0..20).map(|x| x.to_string()).collect(); + let range = 0..vec.len(); + let convec = vec.into_concurrent(); + let (growth, data, capacity) = convec.destruct(); + + ConcurrentFixedVecIntoIter::new(data, range) + }; + + let consume_all = iter().count(); + assert_eq!(consume_all, 20); + + let mut consume_half = iter(); + for _ in 0..10 { + _ = consume_half.next(); + } + + let _consume_none = iter(); +} From 56125161b2ac04ff485b301627e70ac9a5d9e3dd Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:51:39 +0200 Subject: [PATCH 14/27] fix destruct to zero capacity --- Cargo.toml | 2 +- src/concurrent_pinned_vec/con_pinvec.rs | 11 +++++------ src/concurrent_pinned_vec/tests/into_iter.rs | 7 +++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index defd9cd..494def5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orx-split-vec" -version = "3.20.0" +version = "3.21.0" edition = "2024" authors = ["orxfun "] description = "An efficient dynamic capacity vector with pinned element guarantees." diff --git a/src/concurrent_pinned_vec/con_pinvec.rs b/src/concurrent_pinned_vec/con_pinvec.rs index 47cc3ff..697332c 100644 --- a/src/concurrent_pinned_vec/con_pinvec.rs +++ b/src/concurrent_pinned_vec/con_pinvec.rs @@ -38,11 +38,10 @@ impl ConcurrentSplitVec { pub(super) fn destruct(mut self) -> (G, Vec>, usize) { let mut data = Vec::new(); core::mem::swap(&mut self.data, &mut data); - ( - self.growth.clone(), - data, - self.capacity.load(Ordering::Relaxed), - ) + let capacity = self.capacity.load(Ordering::Relaxed); + let growth = self.growth.clone(); + self.zero(); + (growth, data, capacity) } unsafe fn get_raw_mut_unchecked_fi(&self, f: usize, i: usize) -> *mut T { @@ -447,7 +446,7 @@ impl ConcurrentPinnedVec for ConcurrentSp IterPtrOfCon::new(self.capacity(), &self.data, self.growth.clone(), range) } - unsafe fn into_iter(self, range: Range) -> Self::IntoIter { + unsafe fn into_iter(mut self, range: Range) -> Self::IntoIter { let (growth, data, capacity) = self.destruct(); ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) } diff --git a/src/concurrent_pinned_vec/tests/into_iter.rs b/src/concurrent_pinned_vec/tests/into_iter.rs index 92e7c82..85eef83 100644 --- a/src/concurrent_pinned_vec/tests/into_iter.rs +++ b/src/concurrent_pinned_vec/tests/into_iter.rs @@ -1,16 +1,15 @@ -use crate::{Doubling, SplitVec}; +use crate::{Doubling, SplitVec, concurrent_pinned_vec::into_iter::ConcurrentSplitVecIntoIter}; use orx_pinned_vec::{IntoConcurrentPinnedVec, PinnedVec}; use std::string::ToString; #[test] -fn into_iter_non_taken() { +fn into_iter_non_taken_doubling() { let iter = || { let vec: SplitVec<_, Doubling> = (0..20).map(|x| x.to_string()).collect(); let range = 0..vec.len(); let convec = vec.into_concurrent(); let (growth, data, capacity) = convec.destruct(); - - ConcurrentFixedVecIntoIter::new(data, range) + ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) }; let consume_all = iter().count(); From 15c4be3e2f779c4026138b97d80298260daf9afe Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:52:24 +0200 Subject: [PATCH 15/27] clippy fix --- src/concurrent_pinned_vec/con_pinvec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concurrent_pinned_vec/con_pinvec.rs b/src/concurrent_pinned_vec/con_pinvec.rs index 697332c..c6a3947 100644 --- a/src/concurrent_pinned_vec/con_pinvec.rs +++ b/src/concurrent_pinned_vec/con_pinvec.rs @@ -446,7 +446,7 @@ impl ConcurrentPinnedVec for ConcurrentSp IterPtrOfCon::new(self.capacity(), &self.data, self.growth.clone(), range) } - unsafe fn into_iter(mut self, range: Range) -> Self::IntoIter { + unsafe fn into_iter(self, range: Range) -> Self::IntoIter { let (growth, data, capacity) = self.destruct(); ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) } From fcd2c02ea95c11db2e898396fbdff9e52dcf75b6 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 21:58:14 +0200 Subject: [PATCH 16/27] into iter tests made generic over growth --- src/concurrent_pinned_vec/tests/into_iter.rs | 28 ++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/concurrent_pinned_vec/tests/into_iter.rs b/src/concurrent_pinned_vec/tests/into_iter.rs index 85eef83..fe5a1ce 100644 --- a/src/concurrent_pinned_vec/tests/into_iter.rs +++ b/src/concurrent_pinned_vec/tests/into_iter.rs @@ -1,11 +1,29 @@ -use crate::{Doubling, SplitVec, concurrent_pinned_vec::into_iter::ConcurrentSplitVecIntoIter}; +use crate::{ + Doubling, GrowthWithConstantTimeAccess, Linear, SplitVec, + concurrent_pinned_vec::into_iter::ConcurrentSplitVecIntoIter, +}; use orx_pinned_vec::{IntoConcurrentPinnedVec, PinnedVec}; -use std::string::ToString; +use std::string::{String, ToString}; +use test_case::test_matrix; -#[test] -fn into_iter_non_taken_doubling() { +fn vec_doubling() -> SplitVec { + (0..20).map(|x| x.to_string()).collect() +} + +fn vec_linear() -> SplitVec { + let mut vec = SplitVec::with_linear_growth(2); + vec.extend((0..20).map(|x| x.to_string())); + vec +} + +#[test_matrix([vec_doubling, vec_linear])] +fn into_iter_non_taken(vec: F) +where + G: GrowthWithConstantTimeAccess, + F: Fn() -> SplitVec, +{ let iter = || { - let vec: SplitVec<_, Doubling> = (0..20).map(|x| x.to_string()).collect(); + let vec = vec(); let range = 0..vec.len(); let convec = vec.into_concurrent(); let (growth, data, capacity) = convec.destruct(); From a8acc13ac53352f764fead22017e3b5e3c69f974 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 22:04:40 +0200 Subject: [PATCH 17/27] into iter tests are implemented --- src/concurrent_pinned_vec/tests/into_iter.rs | 97 +++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/src/concurrent_pinned_vec/tests/into_iter.rs b/src/concurrent_pinned_vec/tests/into_iter.rs index fe5a1ce..7260cb5 100644 --- a/src/concurrent_pinned_vec/tests/into_iter.rs +++ b/src/concurrent_pinned_vec/tests/into_iter.rs @@ -2,7 +2,7 @@ use crate::{ Doubling, GrowthWithConstantTimeAccess, Linear, SplitVec, concurrent_pinned_vec::into_iter::ConcurrentSplitVecIntoIter, }; -use orx_pinned_vec::{IntoConcurrentPinnedVec, PinnedVec}; +use orx_pinned_vec::{ConcurrentPinnedVec, IntoConcurrentPinnedVec, PinnedVec}; use std::string::{String, ToString}; use test_case::test_matrix; @@ -40,3 +40,98 @@ where let _consume_none = iter(); } + +#[test_matrix([vec_doubling, vec_linear])] +fn into_iter_taken_from_beg(vec: F) +where + G: GrowthWithConstantTimeAccess, + F: Fn() -> SplitVec, +{ + let iter = || { + let vec = vec(); + let range = 5..vec.len(); + let convec = vec.into_concurrent(); + + for i in 0..range.start { + let p = unsafe { convec.get_ptr_mut(i) }; + let _value = unsafe { p.read() }; + } + + let (growth, data, capacity) = convec.destruct(); + ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) + }; + + let consume_all = iter().count(); + assert_eq!(consume_all, 15); + + let mut consume_half = iter(); + for _ in 0..10 { + _ = consume_half.next(); + } + + let _consume_none = iter(); +} + +#[test_matrix([vec_doubling, vec_linear])] +fn into_iter_taken_from_end(vec: F) +where + G: GrowthWithConstantTimeAccess, + F: Fn() -> SplitVec, +{ + let iter = || { + let vec = vec(); + let vec_len = vec.len(); + let range = 0..15; + let convec = vec.into_concurrent(); + + for i in range.end..vec_len { + let p = unsafe { convec.get_ptr_mut(i) }; + let _value = unsafe { p.read() }; + } + + let (growth, data, capacity) = convec.destruct(); + ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) + }; + + let consume_all = iter().count(); + assert_eq!(consume_all, 15); + + let mut consume_half = iter(); + for _ in 0..10 { + _ = consume_half.next(); + } + + let _consume_none = iter(); +} + +#[test_matrix([vec_doubling, vec_linear])] +fn into_iter_taken_from_both_ends(vec: F) +where + G: GrowthWithConstantTimeAccess, + F: Fn() -> SplitVec, +{ + let iter = || { + let vec = vec(); + let vec_len = vec.len(); + let range = 4..15; + let convec = vec.into_concurrent(); + + for i in (0..range.start).chain(range.end..vec_len) { + let p = unsafe { convec.get_ptr_mut(i) }; + let _value = unsafe { p.read() }; + } + + let (growth, data, capacity) = convec.destruct(); + ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) + }; + + let consume_all = iter().count(); + assert_eq!(consume_all, 11); + + let mut consume_half = iter(); + for _ in 0..7 { + _ = consume_half.next(); + } + + let _consume_none = iter(); +} From c3ff5aef5199b67312caba7dd4e6134d59d4e0d7 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 22:39:48 +0200 Subject: [PATCH 18/27] fix memory leak with empty iter --- .../into_iter_ptr_slices.rs | 31 +++++++----- src/concurrent_pinned_vec/tests/into_iter.rs | 49 ++++++++++++++----- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs index c2a7821..d9326e0 100644 --- a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -26,16 +26,7 @@ where G: GrowthWithConstantTimeAccess, { fn drop(&mut self) { - for f in 0..self.fragments.len() { - let ptr = unsafe { *self.fragments[f].get() }; - match ptr.is_null() { - true => break, - false => { - let capacity = self.capacity_of(f); - let _fragment_to_drop = unsafe { fragment_from_raw(ptr, 0, capacity) }; - } - } - } + Self::drop_fragments(&self.growth, &mut self.fragments); } } @@ -77,7 +68,7 @@ where pub fn new( capacity: usize, - fragments: Vec>, + mut fragments: Vec>, growth: G, range: Range, ) -> Self { @@ -87,7 +78,10 @@ where let b = min(capacity, range_end(&range, capacity)); match b.saturating_sub(a) { - 0 => Self::empty(), + 0 => { + Self::drop_fragments(&growth, &mut fragments); + Self::empty() + } _ => { let (sf, si) = fragment_and_inner_indices(a); let (ef, ei) = fragment_and_inner_indices(b - 1); @@ -112,6 +106,19 @@ where } } + fn drop_fragments(growth: &G, fragments: &mut Vec>) { + for f in 0..fragments.len() { + let ptr = unsafe { *fragments[f].get() }; + match ptr.is_null() { + true => continue, + false => { + let capacity = growth.fragment_capacity_of(f); + let _fragment_to_drop = unsafe { fragment_from_raw(ptr, 0, capacity) }; + } + } + } + } + #[inline(always)] fn remaining_len(&self) -> usize { (1 + self.ef).saturating_sub(self.f) diff --git a/src/concurrent_pinned_vec/tests/into_iter.rs b/src/concurrent_pinned_vec/tests/into_iter.rs index 7260cb5..4f7d1f7 100644 --- a/src/concurrent_pinned_vec/tests/into_iter.rs +++ b/src/concurrent_pinned_vec/tests/into_iter.rs @@ -6,24 +6,49 @@ use orx_pinned_vec::{ConcurrentPinnedVec, IntoConcurrentPinnedVec, PinnedVec}; use std::string::{String, ToString}; use test_case::test_matrix; -fn vec_doubling() -> SplitVec { - (0..20).map(|x| x.to_string()).collect() +fn vec_doubling(n: usize) -> SplitVec { + (0..n).map(|x| x.to_string()).collect() } -fn vec_linear() -> SplitVec { +fn vec_linear(n: usize) -> SplitVec { let mut vec = SplitVec::with_linear_growth(2); - vec.extend((0..20).map(|x| x.to_string())); + vec.extend((0..n).map(|x| x.to_string())); vec } +#[test_matrix([vec_doubling, vec_linear])] +fn into_iter_empty(vec: F) +where + G: GrowthWithConstantTimeAccess, + F: Fn(usize) -> SplitVec, +{ + let iter = || { + let vec = vec(0); + let range = 0..vec.len(); + let convec = vec.into_concurrent(); + let (growth, data, capacity) = convec.destruct(); + ConcurrentSplitVecIntoIter::new(capacity, data, growth, range) + }; + + let consume_all = iter().count(); + assert_eq!(consume_all, 0); + + let mut consume_half = iter(); + for _ in 0..10 { + _ = consume_half.next(); + } + + let _consume_none = iter(); +} + #[test_matrix([vec_doubling, vec_linear])] fn into_iter_non_taken(vec: F) where G: GrowthWithConstantTimeAccess, - F: Fn() -> SplitVec, + F: Fn(usize) -> SplitVec, { let iter = || { - let vec = vec(); + let vec = vec(20); let range = 0..vec.len(); let convec = vec.into_concurrent(); let (growth, data, capacity) = convec.destruct(); @@ -45,10 +70,10 @@ where fn into_iter_taken_from_beg(vec: F) where G: GrowthWithConstantTimeAccess, - F: Fn() -> SplitVec, + F: Fn(usize) -> SplitVec, { let iter = || { - let vec = vec(); + let vec = vec(20); let range = 5..vec.len(); let convec = vec.into_concurrent(); @@ -76,10 +101,10 @@ where fn into_iter_taken_from_end(vec: F) where G: GrowthWithConstantTimeAccess, - F: Fn() -> SplitVec, + F: Fn(usize) -> SplitVec, { let iter = || { - let vec = vec(); + let vec = vec(20); let vec_len = vec.len(); let range = 0..15; let convec = vec.into_concurrent(); @@ -108,10 +133,10 @@ where fn into_iter_taken_from_both_ends(vec: F) where G: GrowthWithConstantTimeAccess, - F: Fn() -> SplitVec, + F: Fn(usize) -> SplitVec, { let iter = || { - let vec = vec(); + let vec = vec(20); let vec_len = vec.len(); let range = 4..15; let convec = vec.into_concurrent(); From 4b72715dbd7d683e9bc991c27ae6e9f90fb813e9 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 23:35:45 +0200 Subject: [PATCH 19/27] impl default for IterPtrOfCon --- src/concurrent_pinned_vec/iter_ptr.rs | 14 ++++++++++++++ src/concurrent_pinned_vec/iter_ptr_slices.rs | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/src/concurrent_pinned_vec/iter_ptr.rs b/src/concurrent_pinned_vec/iter_ptr.rs index eb84fb3..4280741 100644 --- a/src/concurrent_pinned_vec/iter_ptr.rs +++ b/src/concurrent_pinned_vec/iter_ptr.rs @@ -13,6 +13,20 @@ where current_last: *const T, } +impl<'a, T, G> Default for IterPtrOfCon<'a, T, G> +where + G: GrowthWithConstantTimeAccess, +{ + fn default() -> Self { + Self { + slices: IterPtrOfConSlices::default(), + len_of_remaining_slices: 0, + current_ptr: core::ptr::null(), + current_last: core::ptr::null(), + } + } +} + impl<'a, T, G> IterPtrOfCon<'a, T, G> where G: GrowthWithConstantTimeAccess, diff --git a/src/concurrent_pinned_vec/iter_ptr_slices.rs b/src/concurrent_pinned_vec/iter_ptr_slices.rs index f956bc4..4c600f6 100644 --- a/src/concurrent_pinned_vec/iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/iter_ptr_slices.rs @@ -19,6 +19,15 @@ where f: usize, } +impl<'a, T, G> Default for IterPtrOfConSlices<'a, T, G> +where + G: GrowthWithConstantTimeAccess, +{ + fn default() -> Self { + Self::empty() + } +} + impl<'a, T, G> IterPtrOfConSlices<'a, T, G> where G: GrowthWithConstantTimeAccess, From 61434920a98749c27a40857197d1afacf0ae32c4 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 27 Sep 2025 23:38:32 +0200 Subject: [PATCH 20/27] test iter_ptr_default --- src/concurrent_pinned_vec/tests/iter_ptr.rs | 17 +++++++++++++++++ src/concurrent_pinned_vec/tests/mod.rs | 1 + 2 files changed, 18 insertions(+) create mode 100644 src/concurrent_pinned_vec/tests/iter_ptr.rs diff --git a/src/concurrent_pinned_vec/tests/iter_ptr.rs b/src/concurrent_pinned_vec/tests/iter_ptr.rs new file mode 100644 index 0000000..66d8a73 --- /dev/null +++ b/src/concurrent_pinned_vec/tests/iter_ptr.rs @@ -0,0 +1,17 @@ +use crate::GrowthWithConstantTimeAccess; +use crate::concurrent_pinned_vec::iter_ptr::IterPtrOfCon; +use crate::{Doubling, Linear}; +use std::string::String; +use test_case::test_matrix; + +#[test_matrix([ + Doubling, + Linear::new(4), +])] +fn iter_ptr_default(_: G) +where + G: GrowthWithConstantTimeAccess, +{ + let iter = IterPtrOfCon::::default(); + for _ in iter {} +} diff --git a/src/concurrent_pinned_vec/tests/mod.rs b/src/concurrent_pinned_vec/tests/mod.rs index 505e27f..c6ea9db 100644 --- a/src/concurrent_pinned_vec/tests/mod.rs +++ b/src/concurrent_pinned_vec/tests/mod.rs @@ -1 +1,2 @@ mod into_iter; +mod iter_ptr; From c29fa4bfbc92ffa41d9925237273317af182fdda Mon Sep 17 00:00:00 2001 From: orxfun Date: Tue, 30 Sep 2025 19:55:50 +0200 Subject: [PATCH 21/27] upgrade pinned-vec dependency --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 494def5..f014d6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,7 @@ categories = ["data-structures", "rust-patterns", "no-std"] [dependencies] orx-iterable = { version = "1.3.0", default-features = false } orx-pseudo-default = { version = "2.1.0", default-features = false } -# orx-pinned-vec = { version = "3.18.0", default-features = false } -orx-pinned-vec = { git = "https://github.com/orxfun/orx-pinned-vec", branch = "into-iter-for-concurrent-pinned-vectors" } +orx-pinned-vec = { version = "3.19.0", default-features = false } orx-concurrent-iter = { version = "3.1.0", default-features = false } [[bench]] From 12d422ff9ca08268210175af9942626c63bb774b Mon Sep 17 00:00:00 2001 From: orxfun Date: Tue, 30 Sep 2025 20:40:46 +0200 Subject: [PATCH 22/27] impl Default for ConcurrentSplitVecIntoIter --- src/concurrent_pinned_vec/into_iter.rs | 14 ++++++++++++++ src/concurrent_pinned_vec/into_iter_ptr_slices.rs | 1 + 2 files changed, 15 insertions(+) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 27ba443..3dcfc01 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -15,6 +15,20 @@ where current_last: *const T, } +impl<'a, T, G> Default for ConcurrentSplitVecIntoIter +where + G: GrowthWithConstantTimeAccess, +{ + fn default() -> Self { + Self { + slices: Default::default(), + len_of_remaining_slices: Default::default(), + current_ptr: Default::default(), + current_last: Default::default(), + } + } +} + impl<'a, T, G> ConcurrentSplitVecIntoIter where G: GrowthWithConstantTimeAccess, diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs index d9326e0..38f232e 100644 --- a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -7,6 +7,7 @@ use alloc::vec::Vec; use core::cmp::min; use core::{cell::UnsafeCell, iter::FusedIterator, ops::Range}; +#[derive(Default)] pub(super) struct IntoIterPtrOfConSlices where G: GrowthWithConstantTimeAccess, From 715a1120814ae78cefff88d74ff61289de19d368 Mon Sep 17 00:00:00 2001 From: orxfun Date: Tue, 30 Sep 2025 21:49:42 +0200 Subject: [PATCH 23/27] upgrade pinned vec version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f014d6e..be45983 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ categories = ["data-structures", "rust-patterns", "no-std"] [dependencies] orx-iterable = { version = "1.3.0", default-features = false } orx-pseudo-default = { version = "2.1.0", default-features = false } -orx-pinned-vec = { version = "3.19.0", default-features = false } +orx-pinned-vec = { version = "3.20.0", default-features = false } orx-concurrent-iter = { version = "3.1.0", default-features = false } [[bench]] From 60759dcf1f00e7292c90548f92b8586911153f25 Mon Sep 17 00:00:00 2001 From: orxfun Date: Tue, 30 Sep 2025 21:52:54 +0200 Subject: [PATCH 24/27] remove IntoIter default implementation --- src/concurrent_pinned_vec/into_iter.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 3dcfc01..27ba443 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -15,20 +15,6 @@ where current_last: *const T, } -impl<'a, T, G> Default for ConcurrentSplitVecIntoIter -where - G: GrowthWithConstantTimeAccess, -{ - fn default() -> Self { - Self { - slices: Default::default(), - len_of_remaining_slices: Default::default(), - current_ptr: Default::default(), - current_last: Default::default(), - } - } -} - impl<'a, T, G> ConcurrentSplitVecIntoIter where G: GrowthWithConstantTimeAccess, From c954cd2ce10e09efeb0603ef13da0d0287a83121 Mon Sep 17 00:00:00 2001 From: orxfun Date: Tue, 30 Sep 2025 22:26:04 +0200 Subject: [PATCH 25/27] temporarily exclude tests with con bag --- src/concurrent_iter/tests/con_iter_owned/mod.rs | 4 ++-- src/concurrent_iter/tests/con_iter_ref/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/concurrent_iter/tests/con_iter_owned/mod.rs b/src/concurrent_iter/tests/con_iter_owned/mod.rs index bc15087..cd80447 100644 --- a/src/concurrent_iter/tests/con_iter_owned/mod.rs +++ b/src/concurrent_iter/tests/con_iter_owned/mod.rs @@ -1,4 +1,4 @@ -mod con_iter; -mod into; +// mod con_iter; +// mod into; mod par; mod transformations; diff --git a/src/concurrent_iter/tests/con_iter_ref/mod.rs b/src/concurrent_iter/tests/con_iter_ref/mod.rs index bc15087..cd80447 100644 --- a/src/concurrent_iter/tests/con_iter_ref/mod.rs +++ b/src/concurrent_iter/tests/con_iter_ref/mod.rs @@ -1,4 +1,4 @@ -mod con_iter; -mod into; +// mod con_iter; +// mod into; mod par; mod transformations; From 17cda97900a15c6ea29245759e7cb6073823d225 Mon Sep 17 00:00:00 2001 From: orxfun Date: Tue, 30 Sep 2025 22:33:50 +0200 Subject: [PATCH 26/27] temporarily exclude con-bag from tests --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index be45983..8dc4047 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,4 +24,4 @@ criterion = "0.7.0" rand = { version = "0.9.2", default-features = false } rand_chacha = { version = "0.9", default-features = false } test-case = "3.3.1" -orx-concurrent-bag = "3.1.0" +# orx-concurrent-bag = "3.1.0" From b801ef7a16a75d52f1d543c60bd0b7c68c620cbd Mon Sep 17 00:00:00 2001 From: orxfun Date: Wed, 1 Oct 2025 14:51:58 +0200 Subject: [PATCH 27/27] clippy fixes --- src/concurrent_pinned_vec/into_iter.rs | 2 +- src/concurrent_pinned_vec/into_iter_ptr_slices.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/concurrent_pinned_vec/into_iter.rs b/src/concurrent_pinned_vec/into_iter.rs index 27ba443..ea3d300 100644 --- a/src/concurrent_pinned_vec/into_iter.rs +++ b/src/concurrent_pinned_vec/into_iter.rs @@ -15,7 +15,7 @@ where current_last: *const T, } -impl<'a, T, G> ConcurrentSplitVecIntoIter +impl ConcurrentSplitVecIntoIter where G: GrowthWithConstantTimeAccess, { diff --git a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs index 38f232e..24c5c97 100644 --- a/src/concurrent_pinned_vec/into_iter_ptr_slices.rs +++ b/src/concurrent_pinned_vec/into_iter_ptr_slices.rs @@ -107,9 +107,9 @@ where } } - fn drop_fragments(growth: &G, fragments: &mut Vec>) { - for f in 0..fragments.len() { - let ptr = unsafe { *fragments[f].get() }; + fn drop_fragments(growth: &G, fragments: &mut [UnsafeCell<*mut T>]) { + for (f, cell) in fragments.iter().enumerate() { + let ptr = unsafe { *cell.get() }; match ptr.is_null() { true => continue, false => {