You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
8.0 KiB

//! 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(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(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
{
pub(super) pop: Arc<Populator<'a, T>>,
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>
{
pub(super) pop: &'re mut Populator<'a, T>,
pub(super) idx: usize,
}
impl<'a, T: 'a> PartialEq for OwnedRef<'a, T>
{
#[inline]
fn eq(&self, other: &Self) -> bool
{
address_eq(self.pop.as_ref(), other.pop.as_ref()) && self.idx == other.idx
}
}
impl<'a, T: 'a> PartialOrd for OwnedRef<'a, T>
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if address_eq(self.pop.as_ref(), other.pop.as_ref()) {
self.idx.partial_cmp(&other.idx)
} else {
None
}
}
}
impl<'re, 'a, T: 'a> PartialEq for Ref<'re, 'a, T>
{
#[inline]
fn eq(&self, other: &Self) -> bool
{
address_eq(self.pop, other.pop) && self.idx == other.idx
}
}
impl<'re, 'a, T: 'a> PartialOrd for Ref<'re, 'a, T>
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if address_eq(self.pop, other.pop) {
self.idx.partial_cmp(&other.idx)
} else {
None
}
}
}
impl<'re, 'a, T: 'a> Ref<'re, 'a, T>
{
/// Get a reference to the parent populator
#[inline]
pub fn parent(&self) -> &Populator<'a, T>
{
&self.pop
}
/// The index that this `Ref` refers to.
#[inline]
pub fn slot(&self) -> usize
{
self.idx
}
/// Checks if the references item currently exists.
#[inline]
pub fn exists(&self) -> bool
{
self.inserted.load(atomic::Ordering::SeqCst)
}
/// Try to insert `value` at the referred slot.
///
/// If the slot already has a value, then `Err(value)` is returned, otherwise, `value` is inserted into the table and the number of items now populated is returned.
#[inline]
pub fn try_insert(&self, value: T) -> Result<usize, T>
{
self.pop.try_insert(self.idx, value)
}
/// Insert `value` at the referred slot.
///
/// # Panics
/// If the slot has a value.
#[inline]
pub fn insert(&self, value: T) -> usize
{
self.pop.insert(self.idx, value)
}
/// Consume into the inner populator reference and slot index
#[inline]
pub fn into_parts(self) -> (&'re Populator<'a, T>, usize)
{
(self.pop, self.idx)
}
/// Consume into the inner populator reference
#[inline]
pub fn into_inner(self) -> &'re Populator<'a, T>
{
self.pop
}
}
impl<'a, T:'a> OwnedRef<'a, T>
{
/// Get a reference to the parent `Arc`.
#[inline]
pub fn parent(&self) -> &Arc<Populator<'a, T>>
{
&self.pop
}
/// The index that this `Ref` refers to.
#[inline]
pub fn slot(&self) -> usize
{
self.idx
}
/// Checks if the references item currently exists.
#[inline]
pub fn exists(&self) -> bool
{
self.pop.exists(self.idx)
}
/// Try to insert `value` at the referred slot.
///
/// If the slot already has a value, then `Err(value)` is returned, otherwise, `value` is inserted into the table and the number of items now populated is returned.
#[inline]
pub fn try_insert(&self, value: T) -> Result<usize, T>
{
self.pop.try_insert(self.idx, value)
}
/// Insert `value` at the referred slot.
///
/// # Panics
/// If the slot has a value.
#[inline]
pub fn insert(&self, value: T) -> usize
{
self.pop.insert(self.idx, value)
}
/// Consume into the inner populator and slot index
#[inline]
pub fn into_parts(self) -> (Arc<Populator<'a, T>>, usize)
{
(self.pop, self.idx)
}
/// Consume into the inner populator
#[inline]
pub fn into_inner(self) -> Arc<Populator<'a, T>>
{
self.pop
}
}
//RefEx: Exclusive reference, holds &'re mut Populator<'a, T>
impl<'re, 'a, T: 'a> RefEx<'re, 'a ,T>
{
/// Get a reference to the parent
#[inline]
pub fn parent(&self) -> &Populator<'a, T>
{
&self.pop
}
/// Get a mutable reference to the parent
#[inline]
pub fn parent_mut(&mut self) -> &mut Populator<'a, T>
{
self.pop
}
/// The index that this `RefEx` refers to.
#[inline]
pub fn slot(&self) -> usize
{
self.idx
}
/// Checks if the references item currently exists.
#[inline]
pub fn exists(&mut self) -> bool
{
self.pop.exists_exclusive(self.idx)
}
/// Try to insert `value` at the referred slot.
///
/// If the slot already has a value, then `Err(value)` is returned, otherwise, `value` is inserted into the table and a reference to the new element is returned
#[inline]
pub fn try_insert(&mut self, value: T) -> Result<&T, T>
{
self.pop.try_insert_exclusive(self.idx, value).map(|x| &*x)
}
/// Try to insert `value` at the referred slot.
///
/// If the slot already has a value, then `Err(value)` is returned, otherwise, `value` is inserted into the table and a mutable reference to the new element is returned.
#[inline]
pub fn try_insert_mut(&mut self, value: T) -> Result<&mut T, T>
{
self.pop.try_insert_exclusive(self.idx, value)
}
/// Insert `value` at the referred slot and returns a reference to the inserted element.
///
/// # Panics
/// If the slot has a value.
#[inline]
pub fn insert(&mut self, value: T) -> &T
{
&*self.pop.insert_exclusive(self.idx, value)
}
/// Insert `value` at the referred slot and returns a reference to the inserted element.
///
/// # Panics
/// If the slot has a value.
#[inline]
pub fn insert_mut(&mut self, value: T) -> &mut T
{
self.pop.insert_exclusive(self.idx, value)
}
/// Consume into the inner populator and slot index
#[inline]
pub fn into_parts(self) -> (&'re mut Populator<'a, T>, usize)
{
(self.pop, self.idx)
}
/// Consume into the inner populator
#[inline]
pub fn into_inner(self) -> &'re mut Populator<'a, T>
{
self.pop
}
}
impl<'re, 'a, T: 'a> From<(&'re Populator<'a, T>, usize)> for Ref<'re, 'a, T>
{
#[inline]
fn from((pop, idx): (&'re Populator<'a, T>, usize)) -> Self
{
Self {
pop,
idx,
inserted: &pop.populates[idx]
}
}
}
impl<'re, 'a, T: 'a> From<Ref<'re, 'a, T>> for (&'re Populator<'a, T>, usize)
{
#[inline]
fn from(from: Ref<'re, 'a, T>) -> Self
{
(from.pop, from.idx)
}
}
impl<'a, T: 'a> From<(Arc<Populator<'a, T>>, usize)> for OwnedRef<'a, T>
{
#[inline]
fn from((pop, idx): (Arc<Populator<'a, T>>, usize)) -> Self
{
Self { pop, idx }
}
}
impl<'a, T: 'a> From<OwnedRef<'a, T>> for (Arc<Populator<'a, T>>, usize)
{
#[inline]
fn from(from: OwnedRef<'a, T>) -> Self
{
(from.pop, from.idx)
}
}
impl<'re, 'a, T: 'a> From<RefEx<'re, 'a, T>> for (&'re mut Populator<'a, T>, usize)
{
#[inline]
fn from(from: RefEx<'re, 'a, T>) -> Self {
(from.pop, from.idx)
}
}
impl<'re, 'a, T: 'a> From<(&'re mut Populator<'a, T>, usize)> for RefEx<'re, 'a, T>
{
#[inline]
fn from((pop, idx): (&'re mut Populator<'a, T>, usize)) -> Self
{
Self { pop, idx }
}
}