-
Notifications
You must be signed in to change notification settings - Fork 1
/
stack.rs
116 lines (101 loc) · 3.2 KB
/
stack.rs
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
107
108
109
110
111
112
113
114
115
116
//! Persistent Stack
use crate::ploc::Handle;
use crate::pmem::alloc::Collectable;
use crate::*;
/// Failure of stack operations
#[derive(Debug)]
pub struct TryFail;
/// Persistent stack trait
pub trait Stack<T>: PDefault + Collectable
where
T: Clone,
{
/// Push memento
type Push: Memento;
/// Pop memento
type Pop: Memento;
/// Push
fn push(&self, value: T, mmt: &mut Self::Push, handle: &Handle);
/// Pop
fn pop(&self, mmt: &mut Self::Pop, handle: &Handle) -> Option<T>;
}
pub(crate) mod tests {
use super::*;
use crate::ploc::Handle;
use crate::pmem::alloc::GarbageCollection;
use crate::pmem::*;
use crate::test_utils::tests::*;
pub(crate) struct PushPop<S, const NR_THREAD: usize, const COUNT: usize>
where
S: Stack<TestValue>,
{
pushes: [S::Push; COUNT],
pops: [S::Pop; COUNT],
}
impl<S, const NR_THREAD: usize, const COUNT: usize> Memento for PushPop<S, NR_THREAD, COUNT>
where
S: Stack<TestValue>,
{
fn clear(&mut self) {
for push in self.pushes.as_mut() {
push.clear();
}
for pop in self.pops.as_mut() {
pop.clear();
}
}
}
impl<S, const NR_THREAD: usize, const COUNT: usize> Default for PushPop<S, NR_THREAD, COUNT>
where
S: Stack<TestValue>,
{
fn default() -> Self {
Self {
pushes: array_init::array_init(|_| S::Push::default()),
pops: array_init::array_init(|_| S::Pop::default()),
}
}
}
impl<S, const NR_THREAD: usize, const COUNT: usize> Collectable for PushPop<S, NR_THREAD, COUNT>
where
S: Stack<TestValue>,
{
fn filter(
push_pop: &mut Self,
tid: usize,
gc: &mut GarbageCollection,
pool: &mut PoolHandle,
) {
for push in push_pop.pushes.as_mut() {
S::Push::filter(push, tid, gc, pool);
}
for pop in push_pop.pops.as_mut() {
S::Pop::filter(pop, tid, gc, pool);
}
}
}
impl<S, const NR_THREAD: usize, const COUNT: usize> RootObj<PushPop<S, NR_THREAD, COUNT>>
for TestRootObj<S>
where
S: Stack<TestValue>,
{
/// Concurrent stack test that repeats push and pop
///
/// - Job: Push 1 time with thread's id, then pop 1 time
/// - All threads repeat the job
/// - Finally, it is checked whether the results of all pops so far have the correct cumulative count of each tid value.
fn run(&self, push_pop: &mut PushPop<S, NR_THREAD, COUNT>, handle: &Handle) {
let tid = handle.tid;
let testee = unsafe { TESTER.as_ref().unwrap().testee(true, handle) };
// push; pop;
for seq in 0..COUNT {
let _ = self
.obj
.push(TestValue::new(tid, seq), &mut push_pop.pushes[seq], handle);
let res = self.obj.pop(&mut push_pop.pops[seq], handle);
assert!(res.is_some(), "{tid} {seq}");
testee.report(seq, res.unwrap());
}
}
}
}