extern crate alloc;
use alloc::vec::Vec;
use crate::sync_types;
use core::{marker, ops};
#[derive(Debug)]
pub enum SyncVecError {
MemoryAllocationFailure,
}
pub struct SyncVec<T: marker::Send> {
v: Vec<T>,
pending_reservations_additional_capacity: usize,
}
impl<T: marker::Send> SyncVec<T> {
pub fn new() -> Self {
Self {
v: Vec::new(),
pending_reservations_additional_capacity: 0,
}
}
pub fn try_reserve_exact<'a, L: sync_types::Lock<Self>>(
this: &'a L,
guard: L::Guard<'a>,
additional_capacity: usize,
) -> (L::Guard<'a>, Result<(), SyncVecError>) {
Self::try_reserve_impl(this, guard, additional_capacity, true)
}
pub fn try_reserve<'a, L: sync_types::Lock<Self>>(
this: &'a L,
guard: L::Guard<'a>,
additional_capacity: usize,
) -> (L::Guard<'a>, Result<(), SyncVecError>) {
Self::try_reserve_impl(this, guard, additional_capacity, false)
}
fn try_reserve_impl<'a, L: sync_types::Lock<Self>>(
this: &'a L,
mut guard: L::Guard<'a>,
additional_capacity: usize,
exact: bool,
) -> (L::Guard<'a>, Result<(), SyncVecError>) {
let reallocated_capacity = match guard
.v
.len()
.checked_add(guard.pending_reservations_additional_capacity)
.and_then(|c| c.checked_add(additional_capacity))
{
Some(reallocated_capacity) => reallocated_capacity,
None => return (guard, Err(SyncVecError::MemoryAllocationFailure)),
};
if guard.v.capacity() >= reallocated_capacity {
return (guard, Ok(()));
};
guard.pending_reservations_additional_capacity += additional_capacity;
drop(guard);
let mut reallocated_v = Vec::new();
let allocation_failed = if exact {
reallocated_v.try_reserve_exact(reallocated_capacity).is_err()
} else {
reallocated_v.try_reserve(reallocated_capacity).is_err()
};
if allocation_failed {
let mut guard = this.lock();
guard.pending_reservations_additional_capacity -= additional_capacity;
return (guard, Err(SyncVecError::MemoryAllocationFailure));
}
let mut guard = this.lock();
if guard.v.capacity()
>= reallocated_capacity.min(guard.v.len() + guard.pending_reservations_additional_capacity)
{
guard.pending_reservations_additional_capacity -= additional_capacity;
return (guard, Ok(()));
}
debug_assert!(reallocated_capacity > guard.v.len());
reallocated_v.append(&mut guard.v);
guard.v = reallocated_v;
guard.pending_reservations_additional_capacity -= additional_capacity;
(guard, Ok(()))
}
}
impl<T: marker::Send> ops::Deref for SyncVec<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.v
}
}
impl<T: marker::Send> ops::DerefMut for SyncVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.v
}
}
impl<T: marker::Send> Default for SyncVec<T> {
fn default() -> Self {
Self::new()
}
}