#![feature(fnbox)]
use std::collections::VecDeque;
use std::cell::UnsafeCell;
pub struct DequeCell<T>(UnsafeCell<VecDeque<T>>);
impl<T> DequeCell<T> {
pub fn new() -> Self {
DequeCell(UnsafeCell::new(VecDeque::new()))
}
fn inner(&self) -> &mut VecDeque<T> {
unsafe { &mut *self.0.get() }
}
pub fn push_back(&self, t: T) {
self.inner().push_back(t);
}
pub fn push_front(&self, t: T) {
self.inner().push_front(t);
}
pub fn pop_back(&self) -> Option<T> {
self.inner().pop_back()
}
pub fn pop_front(&self) -> Option<T> {
self.inner().pop_front()
}
pub fn len(&self) -> usize {
self.inner().len()
}
pub fn capacity(&self) -> usize {
self.inner().capacity()
}
pub fn reserve(&self, additional: usize) {
self.inner().reserve(additional);
}
pub fn reserve_exact(&self, additional: usize) {
self.inner().reserve_exact(additional);
}
pub fn is_empty(&self) -> bool {
self.inner().is_empty()
}
pub fn clear(&self) {
self.inner().clear();
}
pub fn drain(&self) -> Drain<T> {
Drain { inner: self }
}
}
pub struct Drain<'a, T: 'a> {
inner: &'a DequeCell<T>,
}
impl<'a, T: 'a> Iterator for Drain<'a, T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
self.inner.pop_front()
}
}
#[cfg(test)]
mod tests {
use super::DequeCell;
use std::boxed::FnBox;
struct Context<T> {
actions: DequeCell<Box<FnBox(&mut Context<T>)>>,
data: T,
}
impl<T> Context<T> {
fn drain(&mut self) {
while let Some(action) = self.actions.pop_front() {
action.call_box((self,));
}
}
fn new(data: T) -> Self {
Context { actions: DequeCell::new(), data: data }
}
}
#[test]
fn interleaved_access() {
let mut c = Context::new(0);
c.actions.push_back(Box::new(|c: &mut Context<i32>| {
assert!(c.data == 0);
c.data += 1;
c.actions.push_back(Box::new(|c: &mut Context<i32>| {
assert!(c.data == 2);
c.data += 1;
}));
}));
c.actions.push_back(Box::new(|c: &mut Context<i32>| {
assert!(c.data == 1);
c.data += 1;
}));
c.drain();
assert!(c.data == 3);
}
}