Added `Iter<"re, "a, T>`: An iterator over a `Populator<"a, T>`, or a slice of elements in that populator. The iterator yields `Ref<"re, "a, T>`, which can be used to insert into the populator or inspect its set-status.

Fortune for parapop's current commit: Curse − 凶
master
Avril 2 years ago
parent 02821a2aa9
commit 4b85a45a27
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -183,11 +183,20 @@ impl<'a, T> Iterator for IntoIter<'a, T>
impl<'a, T> FusedIterator for IntoIter<'a, T>{}
impl<'a, T> ExactSizeIterator for IntoIter<'a, T>{}
/// A reference iterator for a full `Populator<'re, T>`.
#[derive(Debug)]
struct FullIterRef<'a, T>(std::slice::Iter<'a, T>);
//struct PartialIterRef<'a, T>(&) //XXX: This probably isn't possible unless it takes an exclusive reference of Populator<'a, T>. Having to pass 'a around really sucks hey.
pub struct FullIterRef<'re, 'a: 're, T: 'a>(std::slice::Iter<'a, T>, PhantomLifetime<'re>);
impl<'a, T> Iterator for FullIterRef<'a, T>
impl<'re, 'a: 're, T: 'a> FullIterRef<'re, 'a, T>
{
#[inline(always)]
pub(super) fn new(slice: &'a [T]) -> Self
{
Self (slice.iter(), PhantomLifetime::new())
}
}
impl<'re, 'a: 're, T: 'a> Iterator for FullIterRef<'re, 'a, T>
{
type Item = &'a T;
#[inline]
@ -200,14 +209,166 @@ impl<'a, T> Iterator for FullIterRef<'a, T>
}
}
impl<'a, T> DoubleEndedIterator for FullIterRef<'a, T>
impl<'re, 'a: 're, T: 'a> DoubleEndedIterator for FullIterRef<'re, 'a, T>
{
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<'a, T> FusedIterator for FullIterRef<'a, T>{}
impl<'a, T> ExactSizeIterator for FullIterRef<'a, T>{}
impl<'re, 'a: 're, T: 'a> FusedIterator for FullIterRef<'re, 'a, T>{}
impl<'re, 'a: 're, T: 'a> ExactSizeIterator for FullIterRef<'re, 'a, T>{}
/// A mutable reference iterator for a full `Populator<'re, T>`.
#[derive(Debug)]
pub struct FullIterMut<'re, 'a: 're, T: 'a>(std::slice::IterMut<'a, T>, PhantomLifetime<'re>);
impl<'re, 'a: 're, T: 'a> FullIterMut<'re, 'a, T>
{
#[inline(always)]
pub(super) fn new(slice: &'a mut [T]) -> Self
{
Self (slice.iter_mut(), PhantomLifetime::new())
}
}
impl<'re, 'a: 're, T: 'a> Iterator for FullIterMut<'re, 'a, T>
{
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'re, 'a: 're, T: 'a> DoubleEndedIterator for FullIterMut<'re, 'a, T>
{
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<'re, 'a: 're, T: 'a> FusedIterator for FullIterMut<'re, 'a, T>{}
impl<'re, 'a: 're, T: 'a> ExactSizeIterator for FullIterMut<'re, 'a, T>{}
/// Internal iterator over a `Populator<'a, T>`
#[derive(Debug, Clone)] // PartialEq, Eq
struct IterInternal<'a, T>
{
//pop: &'re Populator<'a, T>,
values: std::slice::Iter<'a, MaybeUninit<T>>,
populated: std::slice::Iter<'a, AtomicBool>, //XXX: When the iterator ends, this iter will be 1 item behind `values`, so use `values` for size hint.
}
impl<'a, T: 'a> Iterator for IterInternal<'a, T>
{
type Item = (&'a MaybeUninit<T>, &'a AtomicBool);
#[inline]
fn next(&mut self) -> Option<Self::Item>
{
self.values.next()
.and_then(move |v| self.populated.next()
.map(move |p| (v, p)))
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.values.size_hint()
}
}
/// An iterator over a full populator, or a range inside a populator.
#[derive(Debug, Clone)] // PartialEq, Eq
pub struct Iter<'re, 'a, T>{
pop: &'re Populator<'a, T>,
indecies: <std::ops::Range<usize> as IntoIterator>::IntoIter,
}
impl<'re, 'a, T: 'a> Eq for Iter<'re, 'a, T>{}
impl<'re, 'a, T: 'a> PartialEq for Iter<'re, 'a, T>
{
#[inline]
fn eq(&self, other: &Self) -> bool
{
std::ptr::eq(self.pop, other.pop)
&& self.indecies == other.indecies
}
}
impl<'re, 'a: 're, T: 'a> Iter<'re, 'a, T>
{
#[inline]
fn create_from(&self, idx: usize) -> Ref<'re, 'a, T>
{
Ref {
pop: self.pop,
inserted: &self.pop.populates[idx],
idx,
}
}
#[inline(always)]
pub(crate) fn new_range(pop: &'re Populator<'a, T>, indecies: std::ops::Range<usize>) -> Self
{
Self {
pop,
indecies
}
}
pub(crate) fn new_ranged(pop: &'re Populator<'a, T>, indecies: impl Into<(usize, usize)>) -> Self
{
let (a, b) = indecies.into();
Self {
indecies: (a..b),
pop,
}
}
#[inline(always)]
pub(crate) fn new(pop: &'re Populator<'a, T>) -> Self
{
Self::new_ranged(pop, (0, pop.len()))
}
}
#[inline(always)]
fn create_from_iter<'iter, 're, 'a: 're, T: 'a>(iter: &'iter Iter<'re, 'a, T>) -> impl Fn(usize) -> Ref<'re, 'a, T> + 'iter
{
move |idx| iter.create_from(idx)
}
impl<'re, 'a: 're, T: 'a> Iterator for Iter<'re, 'a, T>
{
type Item = Ref<'re, 'a, T>;
#[inline]
fn next(&mut self) -> Option<Self::Item>
{
self.indecies.next().map(create_from_iter(self))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.indecies.size_hint()
}
#[inline]
fn nth(&mut self, idx: usize) -> Option<Self::Item>
{
self.indecies.nth(idx).map(create_from_iter(self))
}
}
impl<'re, 'a: 're, T: 'a> FusedIterator for Iter<'re, 'a, T>{}
impl<'re, 'a: 're, T: 'a> ExactSizeIterator for Iter<'re, 'a, T>{}
impl<'re, 'a: 're, T: 'a> DoubleEndedIterator for Iter<'re, 'a, T>
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.indecies.next_back().map(create_from_iter(self))
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.indecies.nth_back(n).map(create_from_iter(self))
}
}

@ -423,7 +423,7 @@ impl<'a, T> Populator<'a, T>
/// # Panics
/// If the collection was not full.
#[inline]
pub fn completed_mut(&mut self) -> &[T]
pub fn completed_mut(&mut self) -> &mut [T]
{
self.try_completed_mut().expect("Collection was not fully populated")
}
@ -459,6 +459,69 @@ impl<'a, T> Populator<'a, T>
Err(_) => panic_uncomplete(),
}
}
/// Create an iterator over references to a completed population if it is completed.
#[inline]
pub fn try_completed_iter(&self) -> Option<iter::FullIterRef<'a, '_, T>>
{
self.try_completed_ref().map(iter::FullIterRef::new)
}
/// Create an iterator over references to a completed population.
///
/// # Panics
/// If the collection is not fully populated
#[inline]
pub fn completed_iter(&self) -> iter::FullIterRef<'a, '_, T>
{
iter::FullIterRef::new(self.completed_ref())
}
/// Create a mutable iterator over references to a completed population if it is completed.
#[inline]
pub fn try_completed_iter_mut(&mut self) -> Option<iter::FullIterMut<'a, '_, T>>
{
self.try_completed_mut().map(iter::FullIterMut::new)
}
/// Create a mutable iterator over references to a completed population.
///
/// # Panics
/// If the collection is not fully populated
#[inline]
pub fn completed_iter_mut(&mut self) -> iter::FullIterMut<'a, '_, T>
{
iter::FullIterMut::new(self.completed_mut())
}
/// Create an iterator of references to this `Populator<'a, T>`
#[inline]
pub fn iter(&self) -> iter::Iter<'a, '_, T>
{
iter::Iter::new(self)
}
/// Create an iterator of references to a slice of this `Populator<'a, T>`
///
/// # Panics
/// if `range.end` is larger than `len()`.
#[inline]
pub fn iter_slice(&self, range: impl Into<std::ops::Range<usize>>) -> iter::Iter<'a, '_, T>
{
let range = range.into();
if range.end > self.len() {
#[inline(never)]
#[cold]
fn _panic_oob(end: usize, idx: usize) -> !
{
panic!("Range ends out of the bounds of the populator (length is {end}, range end is {idx})")
}
_panic_oob(self.len(), range.end);
}
iter::Iter::new_range(self, range)
}
}
impl<'a, T: 'a> FromIterator<Option<T>> for Populator<'a, T>
@ -494,10 +557,4 @@ impl<'a, T: 'a> IntoIterator for Populator<'a, T>
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
mod tests;

@ -1,16 +1,18 @@
//! Single-index references.
use super::*;
/// A non-mutable reference to an item in `Populator<'a, T>`, inserted or not.
#[derive(Debug)] // PartialEq, PartialOrd ///XXX: TODO: Should this be Clone (and maybe even Copy)? Check OwnedRef below...
pub struct Ref<'re, 'a, T: 'a>
{
pub(super) pop: &'re Populator<'a, T>,
pub(super) idx: usize,
pub(crate) pop: &'re Populator<'a, T>,
pub(crate) idx: usize,
//TODO: Maybe add inserted bool, or state representing if this Ref has made a change to the populator. The value will be loaded on creation of the Ref, and will be used as a cached version of `completes[idx].load()`
//TODO: OR: Hold a reference to the actual AtomicBool at `idx` itself?
pub(super) inserted: &'re AtomicBool
pub(crate) inserted: &'re AtomicBool
}
/// A mutable reference to an item in `Populator<'a, T>`, inserted or not.
#[derive(Debug, Clone)] // PartialEq, PartialOrd //XXX: TODO: Should this actually be `Clone`? Ref isn't, because its supposed to be a single reference. But since this is arc'd?
pub struct OwnedRef<'a, T: 'a> // PartialEq, PartialOrd
{
@ -18,6 +20,7 @@ pub struct OwnedRef<'a, T: 'a> // PartialEq, PartialOrd
pub(super) idx: usize,
}
/// An exclusive reference to an item in `Populator<'a, T>`, inserted or not.
#[derive(Debug)]
pub struct RefEx<'re, 'a, T: 'a>
{

@ -0,0 +1,9 @@
//! Unit tests
use super::*;
#[test]
fn single_threaded()
{
let pop = Populator::new(10);
//for r in pop.iter
}
Loading…
Cancel
Save