-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Support for Concurrency In version 2, PinnedVec grew with new methods to support concurrent data structures. However, this caused problems since these exposed methods were often unsafe, and further, they were not directly useful for the pinned vector consumers except for concurrent data structures wrapping a pinned vector. Furthermore, they are alien to a regular vector interface that we are used to using. In version 3, a second trait called `ConcurrentPinnedVec` is defined. All useful methods related with concurrent programming are moved to this trait. This trait has an associated type defining the underlying pinned vector type. It can be turned into the pinned vector. Finally, `IntoConcurrentPinnedVec` trait is defined. A pinned vector implementing this trait can be turned into a `ConcurrentPinnedVec`. As explained above, it can be converted back to the pinned vector. This bi-directional transformation allows to wrap pinned vector to have concurrent support, and unwrap whenever concurrency is not required anymore. An important advantage of this approach is that it allowed to clean up the `PinnedVec` api from unsafe and alien concurrency related methods. # Also Tests using clock are revised so that currently pinned vector tests are **miri safe**. `PseudoDefault` is required for all pinned vectors. Note that a `FixedVec` cannot implement a `Default`, but as any type, it can implement a pseudo-default, which is also required for concurrent wrappers.
- Loading branch information
Ugur Arikan (DHL Data & Analytics)
committed
Jul 23, 2024
1 parent
1694406
commit f536ba2
Showing
19 changed files
with
704 additions
and
690 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "orx-split-vec" | ||
version = "2.14.0" | ||
version = "3.0.0" | ||
edition = "2021" | ||
authors = ["orxfun <[email protected]>"] | ||
description = "An efficient constant access time vector with dynamic capacity and pinned elements." | ||
|
@@ -10,7 +10,8 @@ keywords = ["vec", "array", "split", "fragments", "pinned"] | |
categories = ["data-structures", "rust-patterns"] | ||
|
||
[dependencies] | ||
orx-pinned-vec = "2.12" | ||
orx-pseudo-default = "1.0" | ||
orx-pinned-vec = "3.0" | ||
|
||
[[bench]] | ||
name = "serial_access" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use super::iter_fragment::FragmentIter; | ||
use crate::fragment::fragment_struct::Fragment; | ||
use std::iter::FusedIterator; | ||
|
||
/// Iterator over the `SplitVec`. | ||
/// | ||
/// This struct is created by `SplitVec::iter()` method. | ||
#[derive(Debug, Clone)] | ||
#[must_use = "iterators are lazy and do nothing unless consumed"] | ||
pub struct IterCon<'a, T> { | ||
num_fragments: usize, | ||
last_fragment_len: usize, | ||
fragments: &'a [Fragment<T>], | ||
inner: FragmentIter<'a, T>, | ||
f: usize, | ||
} | ||
|
||
impl<'a, T> IterCon<'a, T> { | ||
pub(crate) fn new(fragments: &'a [Fragment<T>], last_fragment_len: usize) -> Self { | ||
assert!(fragments.len() > 0); | ||
|
||
let num_fragments = fragments.len(); | ||
|
||
let first_fragment_len = match num_fragments { | ||
0 => 0, | ||
1 => last_fragment_len, | ||
_ => fragments[0].capacity(), | ||
}; | ||
let inner = FragmentIter::new(&fragments[0], first_fragment_len); | ||
|
||
Self { | ||
num_fragments, | ||
last_fragment_len, | ||
fragments, | ||
inner, | ||
f: 0, | ||
} | ||
} | ||
|
||
fn next_fragment(&mut self) -> Option<&'a T> { | ||
match self.f + 1 < self.num_fragments { | ||
true => { | ||
self.f += 1; | ||
let fragment_len = match self.f == self.num_fragments - 1 { | ||
false => self.fragments[self.f].capacity(), | ||
true => self.last_fragment_len, | ||
}; | ||
self.inner = FragmentIter::new(&self.fragments[self.f], fragment_len); | ||
self.next() | ||
} | ||
false => None, | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> Iterator for IterCon<'a, T> { | ||
type Item = &'a T; | ||
|
||
#[inline(always)] | ||
fn next(&mut self) -> Option<Self::Item> { | ||
let next_element = self.inner.next(); | ||
match next_element.is_some() { | ||
true => next_element, | ||
false => self.next_fragment(), | ||
} | ||
} | ||
} | ||
|
||
impl<T> FusedIterator for IterCon<'_, T> {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use crate::Fragment; | ||
use std::marker::PhantomData; | ||
|
||
#[derive(Debug, Clone)] | ||
pub(crate) struct FragmentIter<'a, T> { | ||
fragment: &'a [T], | ||
i: usize, | ||
phantom: PhantomData<&'a ()>, | ||
} | ||
|
||
impl<'a, T> FragmentIter<'a, T> { | ||
pub(crate) fn new(fragment: &'a Fragment<T>, len: usize) -> Self { | ||
let fragment = unsafe { std::slice::from_raw_parts(fragment.as_ptr(), len) }; | ||
Self { | ||
fragment, | ||
i: 0, | ||
phantom: PhantomData, | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T: 'a> Iterator for FragmentIter<'a, T> { | ||
type Item = &'a T; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
match self.i < self.fragment.len() { | ||
true => { | ||
let element = unsafe { self.fragment.get_unchecked(self.i) }; | ||
self.i += 1; | ||
Some(element) | ||
} | ||
false => None, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.