use std::cmp::Ordering;
use std::collections::binary_heap::BinaryHeap;
use std::borrow::Borrow;
use super::{Handle, HandleIndex};
#[derive(PartialEq, Eq)]
struct InverseHandleIndex(HandleIndex);
impl PartialOrd for InverseHandleIndex {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
other.0.partial_cmp(&self.0)
}
}
impl Ord for InverseHandleIndex {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
pub struct HandlePool {
versions: Vec<HandleIndex>,
frees: BinaryHeap<InverseHandleIndex>,
}
impl HandlePool {
pub fn new() -> HandlePool {
HandlePool {
versions: Vec::new(),
frees: BinaryHeap::new(),
}
}
pub fn with_capacity(capacity: usize) -> HandlePool {
let versions = Vec::with_capacity(capacity);
let mut frees = BinaryHeap::with_capacity(capacity);
for i in 0..versions.len() {
frees.push(InverseHandleIndex(i as HandleIndex));
}
HandlePool {
versions: versions,
frees: frees,
}
}
pub fn create(&mut self) -> Handle {
if self.frees.len() > 0 {
let index = self.frees.pop().unwrap().0 as usize;
self.versions[index] += 1;
Handle::new(index as HandleIndex, self.versions[index])
} else {
self.versions.push(1);
Handle::new(self.versions.len() as HandleIndex - 1, 1)
}
}
pub fn is_alive<T>(&self, handle: T) -> bool
where T: Borrow<Handle>
{
let handle = handle.borrow();
let index = handle.index() as usize;
self.is_alive_at(index) && (self.versions[index] == handle.version())
}
#[inline(always)]
fn is_alive_at(&self, index: usize) -> bool {
(index < self.versions.len()) && ((self.versions[index] & 0x1) == 1)
}
pub fn free<T>(&mut self, handle: T) -> bool
where T: Borrow<Handle>
{
let handle = handle.borrow();
if !self.is_alive(handle) {
false
} else {
self.versions[handle.index() as usize] += 1;
self.frees.push(InverseHandleIndex(handle.index()));
true
}
}
pub fn free_at(&mut self, index: usize) -> Option<Handle> {
if !self.is_alive_at(index) {
None
} else {
self.versions[index] += 1;
self.frees.push(InverseHandleIndex(index as HandleIndex));
Some(Handle::new(index as HandleIndex, self.versions[index] - 1))
}
}
#[inline]
pub fn len(&self) -> usize {
self.versions.len() - self.frees.len()
}
#[inline]
pub fn iter(&self) -> HandleIter {
HandleIter {
versions: &self.versions,
start: 0,
end: self.versions.len() as u32,
}
}
}
#[derive(Copy, Clone)]
pub struct HandleIter<'a> {
versions: &'a Vec<HandleIndex>,
start: HandleIndex,
end: HandleIndex,
}
impl<'a> HandleIter<'a> {
pub fn split_with(&self, len: usize) -> (HandleIter<'a>, HandleIter<'a>) {
let len = len as HandleIndex;
let mid = if self.start + len >= self.end {
self.end
} else {
self.start + len
};
let left = HandleIter {
versions: self.versions,
start: self.start,
end: mid,
};
let right = HandleIter {
versions: self.versions,
start: mid,
end: self.end,
};
(left, right)
}
pub fn split(&self) -> (HandleIter<'a>, HandleIter<'a>) {
let mid = (self.end - self.start) / 2;
self.split_with(mid as usize)
}
pub fn len(&self) -> usize {
(self.end - self.start) as usize
}
}
impl<'a> Iterator for HandleIter<'a> {
type Item = Handle;
fn next(&mut self) -> Option<Handle> {
unsafe {
for i in self.start..self.end {
let v = self.versions.get_unchecked(i as usize);
if v & 0x1 == 1 {
self.start = i + 1;
return Some(Handle::new(i, *v));
}
}
}
None
}
}