1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#![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); } }