use std::ptr;
use std::sync::{Arc, Mutex};
use hibitset::BitSetLike;
pub struct Storage<T> {
vec: Vec<Arc<T>>,
len: Mutex<usize>,
}
unsafe impl<T> Send for Storage<T> {}
unsafe impl<T> Sync for Storage<T> {}
impl<T> Default for Storage<T> {
#[inline]
fn default() -> Self {
Storage {
vec: Vec::default(),
len: Mutex::new(0),
}
}
}
impl<T> Storage<T> {
#[inline]
unsafe fn vec_as_mut(&self) -> &mut Vec<Arc<T>> {
&mut *(&self.vec as *const Vec<Arc<T>> as *mut Vec<Arc<T>>)
}
pub unsafe fn clean<B>(&self, has: B)
where
B: BitSetLike,
{
match self.len.lock() {
Ok(mut len) => {
let mut vec = self.vec_as_mut();
for (i, v) in vec.iter_mut().enumerate() {
if has.contains(i as u32) {
ptr::drop_in_place(v);
}
}
vec.set_len(0);
*len = 0;
}
Err(_) => (),
}
}
#[inline]
pub unsafe fn reserve(&self, index: usize) {
match self.len.lock() {
Ok(mut len) => {
if *len <= index {
let vec = self.vec_as_mut();
let new_len = index + 1;
let delta = new_len - vec.len();
vec.reserve(delta);
vec.set_len(new_len);
*len = new_len;
}
}
Err(_) => (),
}
}
#[inline]
pub unsafe fn insert(&self, id: u32, value: T) {
let index = id as usize;
match self.len.lock() {
Ok(_) => {
ptr::write(self.get_unchecked_mut(index), Arc::new(value));
}
Err(_) => (),
}
}
#[inline]
pub unsafe fn remove(&self, id: u32) -> Arc<T> {
ptr::read(self.get_unchecked(id as usize))
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> &Arc<T> {
self.vec.get_unchecked(index)
}
#[inline]
pub unsafe fn get_unchecked_mut(&self, index: usize) -> &mut Arc<T> {
self.vec_as_mut().get_unchecked_mut(index)
}
#[inline]
pub fn get(&self, id: u32) -> Option<Arc<T>> {
let index = id as usize;
if index < self.vec.len() {
Some(unsafe { self.get_unchecked(index).clone() })
} else {
None
}
}
}