use crate::ConcurrentSlice;
use crate::elem::ConcurrentElement;
use crate::{helpers::DefaultPinVec, state::ConcurrentVecState};
use core::ops::RangeBounds;
use core::sync::atomic::Ordering;
use orx_pinned_concurrent_col::PinnedConcurrentCol;
use orx_pinned_vec::IntoConcurrentPinnedVec;
pub struct ConcurrentVec<T, P = DefaultPinVec<T>>
where
P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
{
pub(crate) core: PinnedConcurrentCol<ConcurrentElement<T>, P::ConPinnedVec, ConcurrentVecState>,
}
impl<T, P> ConcurrentVec<T, P>
where
P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
{
pub fn into_inner(self) -> P {
let len = self.core.state().len();
unsafe { self.core.into_inner(len) }
}
#[inline(always)]
pub(crate) fn reserved_len(&self) -> usize {
let len = self.core.state().len();
let cap = self.core.capacity();
match len <= cap {
true => len,
false => cap,
}
}
pub fn len(&self) -> usize {
let len = self.len_written().load(Ordering::Acquire);
let cap = self.capacity();
let len_reserved = self.len_reserved().load(Ordering::Relaxed);
let until = match len_reserved <= cap {
true => len_reserved,
false => cap,
};
let iter = unsafe { self.core.iter_over_range(len..until) };
let mut num_pushed = 0;
for x in iter {
match x.0.is_some_with_order(Ordering::Relaxed) {
true => num_pushed += 1,
false => break,
}
}
let new_len = len + num_pushed;
self.len_written().fetch_max(new_len, Ordering::Release);
new_len
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn capacity(&self) -> usize {
self.core.capacity()
}
pub fn maximum_capacity(&self) -> usize {
self.core.maximum_capacity()
}
pub fn slice<R: RangeBounds<usize>>(&self, range: R) -> ConcurrentSlice<'_, T, P> {
let [a, b] = orx_pinned_vec::utils::slice::vec_range_limits(&range, Some(self.len()));
let len = b - a;
ConcurrentSlice::new(self, a, len)
}
pub fn as_slice(&self) -> ConcurrentSlice<'_, T, P> {
self.slice(0..self.len())
}
#[inline(always)]
pub fn get(&self, i: usize) -> Option<&ConcurrentElement<T>> {
match i < self.len() {
true => unsafe { self.core.get(i) },
false => None,
}
}
#[inline(always)]
pub fn get_cloned(&self, i: usize) -> Option<T>
where
T: Clone,
{
match i < self.reserved_len() {
true => unsafe { self.core.get(i) }.and_then(|elem| elem.0.clone_into_option()),
false => None,
}
}
#[inline(always)]
pub fn get_copied(&self, i: usize) -> Option<T>
where
T: Copy,
{
self.get_cloned(i)
}
pub fn iter(&self) -> impl Iterator<Item = &ConcurrentElement<T>> {
unsafe { self.core.iter(self.len()) }
}
pub fn iter_cloned(&self) -> impl Iterator<Item = T> + '_
where
T: Clone,
{
unsafe { self.core.iter(self.len()) }.map(|elem| elem.cloned())
}
}
impl<T, P> ConcurrentVec<T, P>
where
P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
{
pub(crate) fn new_from_pinned(pinned_vec: P) -> Self {
Self {
core: PinnedConcurrentCol::new_from_pinned(pinned_vec),
}
}
}
unsafe impl<T: Sync, P: IntoConcurrentPinnedVec<ConcurrentElement<T>>> Sync
for ConcurrentVec<T, P>
{
}
unsafe impl<T: Send, P: IntoConcurrentPinnedVec<ConcurrentElement<T>>> Send
for ConcurrentVec<T, P>
{
}