Skip to content

Commit

Permalink
Merge pull request #49 from orxfun/fill-with-to-enable-concurrent-ini…
Browse files Browse the repository at this point in the history
…tialized-growth

fill with to enable concurrent initialized growth
  • Loading branch information
orxfun authored Aug 12, 2024
2 parents 4fa7803 + 25592ac commit 5d0b013
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 139 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "orx-split-vec"
version = "3.2.0"
version = "3.3.0"
edition = "2021"
authors = ["orxfun <[email protected]>"]
description = "An efficient constant access time vector with dynamic capacity and pinned elements."
Expand All @@ -10,8 +10,8 @@ keywords = ["vec", "array", "split", "fragments", "pinned"]
categories = ["data-structures", "rust-patterns"]

[dependencies]
orx-pseudo-default = "1.2.0"
orx-pinned-vec = "3.2.0"
orx-pseudo-default = "1.2"
orx-pinned-vec = "3.3"

[[bench]]
name = "serial_access"
Expand Down
69 changes: 0 additions & 69 deletions src/common_traits/iterator/iter_con.rs

This file was deleted.

35 changes: 0 additions & 35 deletions src/common_traits/iterator/iter_fragment.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/common_traits/iterator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ mod eq;
mod from_iter;
pub(crate) mod into_iter;
pub(crate) mod iter;
pub(crate) mod iter_con;
mod iter_fragment;
pub(crate) mod iter_mut;
pub(crate) mod iter_mut_rev;
pub(crate) mod iter_rev;
Expand Down
164 changes: 139 additions & 25 deletions src/concurrent_pinned_vec.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
common_traits::iterator::iter_con::IterCon,
fragment::fragment_struct::{
maximum_concurrent_capacity, num_fragments_for_capacity, set_fragments_len,
},
Expand Down Expand Up @@ -44,7 +43,7 @@ impl<T, G: GrowthWithConstantTimeAccess> Drop for ConcurrentSplitVec<T, G> {

impl<T, G: GrowthWithConstantTimeAccess> ConcurrentSplitVec<T, G> {
fn num_fragments(&self) -> usize {
self.num_fragments.load(Ordering::Relaxed)
self.num_fragments.load(Ordering::SeqCst)
}

fn fragments(&self) -> &[Fragment<T>] {
Expand Down Expand Up @@ -124,6 +123,7 @@ impl<T, G: GrowthWithConstantTimeAccess> ConcurrentPinnedVec<T> for ConcurrentSp
let growth = self.growth.clone();

// let (mut fragments, growth) = (self.fragments, self.growth.clone());

SplitVec::from_raw_parts(len, fragments, growth)
}

Expand Down Expand Up @@ -164,6 +164,94 @@ impl<T, G: GrowthWithConstantTimeAccess> ConcurrentPinnedVec<T> for ConcurrentSp
}
}

fn grow_to_and_fill_with<F>(
&self,
new_capacity: usize,
fill_with: F,
) -> Result<usize, orx_pinned_vec::PinnedVecGrowthError>
where
F: Fn() -> T,
{
let capacity = self.capacity();
match new_capacity <= capacity {
true => Ok(capacity),
false => {
let mut num_fragments = self.num_fragments();

let mut current_capacity = capacity;

while new_capacity > current_capacity {
let new_fragment_capacity = self
.growth
.new_fragment_capacity(self.fragments_for(num_fragments));
let mut new_fragment = Fragment::<T>::new(new_fragment_capacity);
for _ in 0..new_fragment_capacity {
new_fragment.push(fill_with());
}

self.push_fragment(new_fragment, num_fragments);

num_fragments += 1;
current_capacity += new_fragment_capacity;
}

self.num_fragments.store(num_fragments, Ordering::SeqCst);
self.capacity.store(current_capacity, Ordering::SeqCst);

Ok(current_capacity)
}
}
}

fn slices<R: RangeBounds<usize>>(&self, range: R) -> <Self::P as PinnedVec<T>>::SliceIter<'_> {
use std::slice::from_raw_parts;

let fragments = self.fragments();
let fragment_and_inner_indices =
|i| self.growth.get_fragment_and_inner_indices_unchecked(i);

let a = range_start(&range);
let b = range_end(&range, self.capacity());

match b.saturating_sub(a) {
0 => vec![],
_ => {
let (sf, si) = fragment_and_inner_indices(a);
let (ef, ei) = fragment_and_inner_indices(b - 1);

match sf == ef {
true => {
let p = self.fragment_element_ptr_mut(sf, si);
let slice = unsafe { from_raw_parts(p, ei - si + 1) };
vec![slice]
}
false => {
let mut vec = Vec::with_capacity(ef - sf + 1);

let slice_len = fragments[sf].capacity() - si;
let ptr_s = self.fragment_element_ptr_mut(sf, si);
let slice = unsafe { from_raw_parts(ptr_s, slice_len) };
vec.push(slice);

for (f, fragment) in fragments.iter().enumerate().take(ef).skip(sf + 1) {
let slice_len = fragment.capacity();
let ptr_s = self.fragment_element_ptr_mut(f, 0);
let slice = unsafe { from_raw_parts(ptr_s, slice_len) };
vec.push(slice);
}

let slice_len = ei + 1;
let ptr_s = self.fragment_element_ptr_mut(ef, 0);
let slice = unsafe { from_raw_parts(ptr_s, slice_len) };
vec.push(slice);

vec
}
}
}
}
}

unsafe fn slices_mut<R: RangeBounds<usize>>(
&self,
range: R,
Expand Down Expand Up @@ -217,36 +305,62 @@ impl<T, G: GrowthWithConstantTimeAccess> ConcurrentPinnedVec<T> for ConcurrentSp
where
T: 'a,
{
use std::slice::from_raw_parts;

let fragments = self.fragments();

match len {
0 => IterCon::new(&fragments[0..1], 0),
let fragment_and_inner_indices =
|i| self.growth.get_fragment_and_inner_indices_unchecked(i);

let range = 0..len;

let a = range_start(&range);
let b = range_end(&range, self.capacity());

let x = match b.saturating_sub(a) {
0 => vec![],
_ => {
// let mut num_fragments = 0;
let mut count = 0;

for (num_fragments, fragment) in fragments.iter().enumerate() {
// for fragment in fragments.iter() {
// num_fragments += 1;
let capacity = fragment.capacity();
let new_count = count + capacity;

match new_count >= len {
true => {
let last_fragment_len = capacity - (new_count - len);
return IterCon::new(
&fragments[0..(num_fragments + 1)],
last_fragment_len,
);
let (sf, si) = fragment_and_inner_indices(a);
let (ef, ei) = fragment_and_inner_indices(b - 1);

match sf == ef {
true => {
let p = fragments[sf].as_ptr().add(si);
let slice = from_raw_parts(p, ei - si + 1);
vec![slice]
}
false => {
let mut vec = Vec::with_capacity(ef - sf + 1);

if let Some(first) = fragments.get(sf) {
let slice_len = first.capacity() - si;

let p = first.as_ptr().add(si);
let slice = from_raw_parts(p, slice_len);
vec.push(slice);
}

for fragment in fragments.iter().take(ef).skip(sf + 1) {
let slice_len = fragment.capacity();
let p = fragment.as_ptr();
let slice = from_raw_parts(p, slice_len);
vec.push(slice);
}

if let Some(last) = fragments.get(ef) {
let slice_len = ei + 1;
let p = last.as_ptr();
let slice = from_raw_parts(p, slice_len);
vec.push(slice);
}
false => count = new_count,

vec
}
}

let last_fragment_len = fragments[fragments.len() - 1].capacity();
IterCon::new(fragments, last_fragment_len)
}
}
};

x.into_iter().flat_map(|x| x.iter())
}

unsafe fn iter_mut<'a>(&'a mut self, len: usize) -> impl Iterator<Item = &'a mut T> + 'a
Expand Down
2 changes: 1 addition & 1 deletion src/growth/doubling/doubling_growth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ mod tests {
let mut curr_capacity = 4;
let mut cumulative_capacity = 4;

for index in 0..1111111 {
for index in 0..51_111 {
if index == cumulative_capacity {
prev_cumulative_capacity = cumulative_capacity;
curr_capacity *= 2;
Expand Down
2 changes: 1 addition & 1 deletion src/growth/linear/linear_growth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ mod tests {
let mut prev_cumulative_capacity = 0;
let mut cumulative_capacity = curr_capacity;

for index in 0..1111111 {
for index in 0..51_111 {
if index == cumulative_capacity {
prev_cumulative_capacity = cumulative_capacity;
cumulative_capacity += curr_capacity;
Expand Down
6 changes: 3 additions & 3 deletions src/growth/recursive/recursive_growth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,9 @@ mod tests {

let mut fragments: Vec<Fragment<_>> = vec![];

let lengths = [30, 52, 14, 1, 7, 3, 79, 248, 147, 530];
let lengths = [30, 1, 7, 3, 79, 147, 530];
let mut index = 0;
for _ in 0..100 {
for _ in 0..10 {
for &len in &lengths {
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
Expand All @@ -266,7 +266,7 @@ mod tests {

let mut index = 0;
let mut f = 0;
for _ in 0..100 {
for _ in 0..10 {
for &len in &lengths {
for i in 0..len {
let maybe_fi =
Expand Down
14 changes: 14 additions & 0 deletions src/into_concurrent_pinned_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,18 @@ impl<T, G: GrowthWithConstantTimeAccess> IntoConcurrentPinnedVec<T> for SplitVec
fn into_concurrent(self) -> Self::ConPinnedVec {
self.into()
}

fn into_concurrent_filled_with<F>(mut self, fill_with: F) -> Self::ConPinnedVec
where
F: Fn() -> T,
{
if let Some(fragment) = self.fragments.last_mut() {
let (len, capacity) = (fragment.len(), fragment.capacity());
for _ in len..capacity {
fragment.push(fill_with());
}
}

self.into()
}
}

0 comments on commit 5d0b013

Please sign in to comment.