Skip to content

Commit 99ceb17

Browse files
authored
Merge pull request #109 from RaduBerinde/deque-test
add a test with a VecDeque structure
2 parents 8b9b2e7 + 3f033e8 commit 99ceb17

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

tests/deque.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use std::cell::Cell;
2+
use std::collections::VecDeque;
3+
use std::rc::Rc;
4+
5+
use left_right::{
6+
aliasing::{Aliased, DropBehavior},
7+
Absorb, ReadHandle,
8+
};
9+
10+
// Value encapsulates an integer value and keeps a registry of live values up to
11+
// date.
12+
struct Value {
13+
v: i32,
14+
r: Rc<ValueRegistry>,
15+
}
16+
17+
impl Value {
18+
fn new(v: i32, r: Rc<ValueRegistry>) -> Self {
19+
r.adjust_count(1);
20+
Self { v, r }
21+
}
22+
}
23+
24+
impl Drop for Value {
25+
fn drop(&mut self) {
26+
self.r.adjust_count(-1);
27+
}
28+
}
29+
30+
// ValueRegistry keeps track of the number of Values that have been created and
31+
// not yet dropped.
32+
struct ValueRegistry {
33+
num_live_values: Cell<i64>,
34+
}
35+
36+
impl ValueRegistry {
37+
fn new() -> Self {
38+
Self {
39+
num_live_values: Cell::new(0),
40+
}
41+
}
42+
43+
fn adjust_count(&self, delta: i64) {
44+
let mut live_vals = self.num_live_values.get();
45+
live_vals += delta;
46+
assert!(live_vals >= 0);
47+
self.num_live_values.set(live_vals);
48+
}
49+
50+
fn expect(&self, expected_count: i64) {
51+
assert_eq!(self.num_live_values.get(), expected_count);
52+
}
53+
}
54+
55+
struct NoDrop;
56+
impl DropBehavior for NoDrop {
57+
const DO_DROP: bool = false;
58+
}
59+
60+
struct DoDrop;
61+
impl DropBehavior for DoDrop {
62+
const DO_DROP: bool = true;
63+
}
64+
type Deque = VecDeque<Aliased<Value, NoDrop>>;
65+
66+
enum Op {
67+
PushBack(Aliased<Value, NoDrop>),
68+
PopFront,
69+
}
70+
71+
impl Absorb<Op> for Deque {
72+
fn absorb_first(&mut self, operation: &mut Op, _other: &Self) {
73+
match operation {
74+
Op::PushBack(value) => {
75+
self.push_back(unsafe { value.alias() });
76+
}
77+
Op::PopFront => {
78+
self.pop_front();
79+
}
80+
}
81+
}
82+
83+
fn absorb_second(&mut self, operation: Op, _other: &Self) {
84+
// Cast the data structure to the variant that drops entries.
85+
// SAFETY: the Aliased type guarantees the same memory layout for NoDrop
86+
// vs DoDrop, so the cast is sound.
87+
let with_drop: &mut VecDeque<Aliased<Value, DoDrop>> =
88+
unsafe { &mut *(self as *mut _ as *mut _) };
89+
match operation {
90+
Op::PushBack(value) => {
91+
with_drop.push_back(unsafe { value.change_drop() });
92+
}
93+
Op::PopFront => {
94+
with_drop.pop_front();
95+
}
96+
}
97+
}
98+
99+
fn sync_with(&mut self, first: &Self) {
100+
assert_eq!(self.len(), 0);
101+
self.extend(first.iter().map(|v| unsafe { v.alias() }));
102+
}
103+
104+
fn drop_first(self: Box<Self>) {
105+
// The Deque type has NoDrop, so this will not drop any of the values.
106+
}
107+
108+
fn drop_second(self: Box<Self>) {
109+
// Convert self to DoDrop and drop it.
110+
let with_drop: Box<VecDeque<Aliased<Value, DoDrop>>> =
111+
unsafe { Box::from_raw(Box::into_raw(self) as *mut _ as *mut _) };
112+
drop(with_drop);
113+
}
114+
}
115+
116+
// Test a deque of aliased values, verifying that the lifetimes of the values
117+
// are as promised.
118+
#[test]
119+
fn deque() {
120+
let registry = Rc::new(ValueRegistry::new());
121+
122+
let mkval = |v| Aliased::from(Value::new(v, Rc::clone(&registry)));
123+
let expect = |r: &ReadHandle<Deque>, expected: &[i32]| {
124+
let guard = r.enter().unwrap();
125+
assert!(guard.iter().map(|v| &v.v).eq(expected.iter()));
126+
};
127+
128+
let (mut w, r) = left_right::new::<Deque, Op>();
129+
w.append(Op::PushBack(mkval(1)));
130+
w.append(Op::PushBack(mkval(2)));
131+
w.append(Op::PushBack(mkval(3)));
132+
w.publish();
133+
134+
registry.expect(3);
135+
expect(&r, &[1, 2, 3]);
136+
137+
w.append(Op::PushBack(mkval(4)));
138+
w.publish();
139+
140+
registry.expect(4);
141+
expect(&r, &[1, 2, 3, 4]);
142+
143+
w.append(Op::PopFront);
144+
w.append(Op::PopFront);
145+
w.publish();
146+
147+
// At this point, the popped values should not be freed.
148+
registry.expect(4);
149+
expect(&r, &[3, 4]);
150+
151+
w.append(Op::PopFront);
152+
w.publish();
153+
154+
// The two previously popped values (1, 2) should have been freed.
155+
registry.expect(2);
156+
expect(&r, &[4]);
157+
158+
drop(r);
159+
drop(w);
160+
161+
registry.expect(0);
162+
}

0 commit comments

Comments
 (0)