use slab::Slab;
use std::cell::{RefCell, RefMut};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::sync::{Mutex, MutexGuard};
pub struct EntryGuard<'a, T> {
entries: RefMut<'a, Slab<T>>,
entry: &'a mut T,
key: usize,
}
impl<T> EntryGuard<'_, T> {
fn remove(mut self) {
self.entries.remove(self.key);
}
}
impl<T> Deref for EntryGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.entry
}
}
impl<T> DerefMut for EntryGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.entry
}
}
pub struct Memory<T> {
entries: RefCell<Slab<T>>,
}
impl<T> Memory<T> {
pub fn new(capacity: usize) -> Self {
let s = Slab::with_capacity(capacity);
Self {
entries: RefCell::new(s),
}
}
#[cfg(test)]
pub fn len(&self) -> usize {
let entries = self.entries.borrow();
entries.len()
}
fn insert(&self, e: T) -> Result<usize, ()> {
let mut entries = self.entries.borrow_mut();
if entries.len() == entries.capacity() {
return Err(());
}
Ok(entries.insert(e))
}
fn get<'a>(&'a self, key: usize) -> Option<EntryGuard<'a, T>> {
let mut entries = self.entries.borrow_mut();
let entry = entries.get_mut(key)?;
let entry = unsafe { mem::transmute::<&mut T, &'a mut T>(entry) };
Some(EntryGuard {
entries,
entry,
key,
})
}
#[cfg(test)]
fn entry0_ptr(&self) -> *const T {
let entries = self.entries.borrow();
entries.get(0).unwrap() as *const T
}
}
pub struct SyncEntryGuard<'a, T> {
entries: MutexGuard<'a, Slab<T>>,
entry: &'a mut T,
key: usize,
}
impl<T> SyncEntryGuard<'_, T> {
fn remove(mut self) {
self.entries.remove(self.key);
}
}
impl<T> Deref for SyncEntryGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.entry
}
}
impl<T> DerefMut for SyncEntryGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.entry
}
}
pub struct SyncMemory<T> {
entries: Mutex<Slab<T>>,
}
impl<T> SyncMemory<T> {
pub fn new(capacity: usize) -> Self {
let s = Slab::with_capacity(capacity);
Self {
entries: Mutex::new(s),
}
}
#[cfg(test)]
pub fn len(&self) -> usize {
let entries = self.entries.lock().unwrap();
entries.len()
}
fn insert(&self, e: T) -> Result<usize, ()> {
let mut entries = self.entries.lock().unwrap();
if entries.len() == entries.capacity() {
return Err(());
}
Ok(entries.insert(e))
}
fn get<'a>(&'a self, key: usize) -> Option<SyncEntryGuard<'a, T>> {
let mut entries = self.entries.lock().unwrap();
let entry = entries.get_mut(key)?;
let entry = unsafe { mem::transmute::<&mut T, &'a mut T>(entry) };
Some(SyncEntryGuard {
entries,
entry,
key,
})
}
#[cfg(test)]
fn entry0_ptr(&self) -> *const T {
let entries = self.entries.lock().unwrap();
entries.get(0).unwrap() as *const T
}
}
pub struct ReusableValue<T> {
reusable: std::sync::Arc<Reusable<T>>,
value: *mut T,
key: usize,
}
impl<T> ReusableValue<T> {
fn get(&self) -> &T {
unsafe { &*self.value }
}
fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.value }
}
}
impl<T> Drop for ReusableValue<T> {
fn drop(&mut self) {
let mut entries = self.reusable.entries.lock().unwrap();
entries.0.remove(self.key);
}
}
impl<T> Deref for ReusableValue<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl<T> DerefMut for ReusableValue<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.get_mut()
}
}
pub struct Reusable<T> {
entries: Mutex<(Slab<()>, Vec<T>)>,
}
impl<T> Reusable<T> {
pub fn new<F>(capacity: usize, init_fn: F) -> Self
where
F: Fn() -> T,
{
let mut values = Vec::with_capacity(capacity);
for _ in 0..capacity {
values.push(init_fn());
}
let s = Slab::with_capacity(capacity);
Self {
entries: Mutex::new((s, values)),
}
}
#[cfg(test)]
pub fn len(&self) -> usize {
let entries = self.entries.lock().unwrap();
entries.0.len()
}
#[allow(clippy::result_unit_err)]
pub fn reserve(self: &std::sync::Arc<Self>) -> Result<ReusableValue<T>, ()> {
let mut entries = self.entries.lock().unwrap();
if entries.0.len() == entries.0.capacity() {
return Err(());
}
let key = entries.0.insert(());
let value = &mut entries.1[key] as *mut T;
Ok(ReusableValue {
reusable: self.clone(),
value,
key,
})
}
}
pub struct RcEntry<T> {
value: T,
refs: usize,
}
pub type RcMemory<T> = Memory<RcEntry<T>>;
pub struct Rc<T> {
memory: std::rc::Rc<RcMemory<T>>,
key: usize,
}
impl<T> Rc<T> {
#[allow(clippy::result_unit_err)]
pub fn new(v: T, memory: &std::rc::Rc<RcMemory<T>>) -> Result<Self, ()> {
let key = memory.insert(RcEntry { value: v, refs: 1 })?;
Ok(Self {
memory: std::rc::Rc::clone(memory),
key,
})
}
#[allow(clippy::should_implement_trait)]
pub fn clone(rc: &Rc<T>) -> Self {
let mut e = rc.memory.get(rc.key).unwrap();
e.refs += 1;
Self {
memory: rc.memory.clone(),
key: rc.key,
}
}
pub fn get<'a>(&'a self) -> &'a T {
let e = self.memory.get(self.key).unwrap();
let value = &e.value;
unsafe { mem::transmute::<&T, &'a T>(value) }
}
}
impl<T> Drop for Rc<T> {
fn drop(&mut self) {
let mut e = self.memory.get(self.key).unwrap();
if e.refs == 1 {
e.remove();
return;
}
e.refs -= 1;
}
}
pub type ArcMemory<T> = SyncMemory<RcEntry<T>>;
pub struct Arc<T> {
memory: std::sync::Arc<ArcMemory<T>>,
key: usize,
}
impl<T> Arc<T> {
#[allow(clippy::result_unit_err)]
pub fn new(v: T, memory: &std::sync::Arc<ArcMemory<T>>) -> Result<Self, ()> {
let key = memory.insert(RcEntry { value: v, refs: 1 })?;
Ok(Self {
memory: memory.clone(),
key,
})
}
#[allow(clippy::should_implement_trait)]
pub fn clone(rc: &Arc<T>) -> Self {
let mut e = rc.memory.get(rc.key).unwrap();
e.refs += 1;
Self {
memory: rc.memory.clone(),
key: rc.key,
}
}
pub fn get<'a>(&'a self) -> &'a T {
let e = self.memory.get(self.key).unwrap();
let value = &e.value;
unsafe { mem::transmute::<&T, &'a T>(value) }
}
}
impl<T> Drop for Arc<T> {
fn drop(&mut self) {
let mut e = self.memory.get(self.key).unwrap();
if e.refs == 1 {
e.remove();
return;
}
e.refs -= 1;
}
}
pub fn recycle_vec<T, U>(mut v: Vec<T>) -> Vec<U> {
assert_eq!(core::mem::size_of::<T>(), core::mem::size_of::<U>());
assert_eq!(core::mem::align_of::<T>(), core::mem::align_of::<U>());
v.clear();
let ptr = v.as_mut_ptr();
let capacity = v.capacity();
mem::forget(v);
let ptr = ptr as *mut U;
unsafe { Vec::from_raw_parts(ptr, 0, capacity) }
}
pub struct ReusableVecHandle<'a, T> {
vec: &'a mut Vec<T>,
}
impl<T> ReusableVecHandle<'_, T> {
pub fn get_ref(&self) -> &Vec<T> {
self.vec
}
pub fn get_mut(&mut self) -> &mut Vec<T> {
self.vec
}
}
impl<T> Drop for ReusableVecHandle<'_, T> {
fn drop(&mut self) {
self.vec.clear();
}
}
impl<T> Deref for ReusableVecHandle<'_, T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
self.get_ref()
}
}
impl<T> DerefMut for ReusableVecHandle<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.get_mut()
}
}
pub struct ReusableVec {
vec: Vec<()>,
size: usize,
align: usize,
}
impl ReusableVec {
pub fn new<T>(capacity: usize) -> Self {
let size = mem::size_of::<T>();
let align = mem::align_of::<T>();
let vec: Vec<T> = Vec::with_capacity(capacity);
let vec: Vec<()> = unsafe { mem::transmute(vec) };
Self { vec, size, align }
}
pub fn get_as_new<U>(&mut self) -> ReusableVecHandle<'_, U> {
let size = mem::size_of::<U>();
let align = mem::align_of::<U>();
assert_eq!(self.size, size);
assert_eq!(self.align, align);
let vec: &mut Vec<()> = &mut self.vec;
let vec: &mut Vec<U> = unsafe { mem::transmute(vec) };
assert!(vec.is_empty());
ReusableVecHandle { vec }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_reusable() {
let reusable = std::sync::Arc::new(Reusable::new(2, || vec![0; 128]));
assert_eq!(reusable.len(), 0);
let mut buf1 = reusable.reserve().unwrap();
assert_eq!(reusable.len(), 1);
let mut buf2 = reusable.reserve().unwrap();
assert_eq!(reusable.len(), 2);
assert!(reusable.reserve().is_err());
buf1[..5].copy_from_slice(b"hello");
buf2[..5].copy_from_slice(b"world");
assert_eq!(&buf1[..5], b"hello");
assert_eq!(&buf2[..5], b"world");
mem::drop(buf1);
assert_eq!(reusable.len(), 1);
mem::drop(buf2);
assert_eq!(reusable.len(), 0);
}
#[test]
fn test_rc() {
let memory = std::rc::Rc::new(RcMemory::new(2));
assert_eq!(memory.len(), 0);
let e0a = Rc::new(123 as i32, &memory).unwrap();
assert_eq!(memory.len(), 1);
let p = memory.entry0_ptr();
let e0b = Rc::clone(&e0a);
assert_eq!(memory.len(), 1);
assert_eq!(memory.entry0_ptr(), p);
let e1a = Rc::new(456 as i32, &memory).unwrap();
assert_eq!(memory.len(), 2);
assert_eq!(memory.entry0_ptr(), p);
assert!(Rc::new(789 as i32, &memory).is_err());
assert_eq!(*e0a.get(), 123);
assert_eq!(*e0b.get(), 123);
assert_eq!(*e1a.get(), 456);
mem::drop(e0b);
assert_eq!(memory.len(), 2);
assert_eq!(memory.entry0_ptr(), p);
mem::drop(e0a);
assert_eq!(memory.len(), 1);
mem::drop(e1a);
assert_eq!(memory.len(), 0);
}
#[test]
fn test_arc() {
let memory = std::sync::Arc::new(ArcMemory::new(2));
assert_eq!(memory.len(), 0);
let e0a = Arc::new(123 as i32, &memory).unwrap();
assert_eq!(memory.len(), 1);
let p = memory.entry0_ptr();
let e0b = Arc::clone(&e0a);
assert_eq!(memory.len(), 1);
assert_eq!(memory.entry0_ptr(), p);
let e1a = Arc::new(456 as i32, &memory).unwrap();
assert_eq!(memory.len(), 2);
assert_eq!(memory.entry0_ptr(), p);
assert!(Arc::new(789 as i32, &memory).is_err());
assert_eq!(*e0a.get(), 123);
assert_eq!(*e0b.get(), 123);
assert_eq!(*e1a.get(), 456);
mem::drop(e0b);
assert_eq!(memory.len(), 2);
assert_eq!(memory.entry0_ptr(), p);
mem::drop(e0a);
assert_eq!(memory.len(), 1);
mem::drop(e1a);
assert_eq!(memory.len(), 0);
}
#[test]
fn test_reusable_vec() {
let mut vec_mem = ReusableVec::new::<u32>(100);
let mut vec = vec_mem.get_as_new::<u32>();
assert_eq!(vec.capacity(), 100);
assert_eq!(vec.len(), 0);
vec.push(1);
assert_eq!(vec.len(), 1);
mem::drop(vec);
let vec = vec_mem.get_as_new::<u32>();
assert_eq!(vec.capacity(), 100);
assert_eq!(vec.len(), 0);
}
}