cs431_homework/elim_stack/
base.rs1use core::marker::PhantomData;
2use core::mem::ManuallyDrop;
3use core::ops::Deref;
4use std::time;
5
6use crossbeam_epoch::{Atomic, Guard, Owned, pin};
7use rand::{self, Rng};
8
9pub(crate) const ELIM_SIZE: usize = 16;
10pub(crate) const ELIM_DELAY: time::Duration = time::Duration::from_millis(10);
11
12#[inline]
13pub(crate) fn get_random_elim_index() -> usize {
14 (rand::rng().random::<u64>() as usize) % ELIM_SIZE
15}
16
17pub trait Stack<T>: Default {
19 type PushReq: From<T> + Deref<Target = ManuallyDrop<T>>;
21
22 fn try_push(
26 &self,
27 req: Owned<Self::PushReq>,
28 guard: &Guard,
29 ) -> Result<(), Owned<Self::PushReq>>;
30
31 fn try_pop(&self, guard: &Guard) -> Result<Option<T>, ()>;
36
37 fn is_empty(&self, guard: &Guard) -> bool;
39
40 fn push(&self, t: T) {
42 let mut req = Owned::new(t.into());
43 let guard = pin();
44 while let Err(r) = self.try_push(req, &guard) {
45 req = r;
46 }
47 }
48
49 fn pop(&self) -> Option<T> {
53 let guard = pin();
54 loop {
55 if let Ok(result) = self.try_pop(&guard) {
56 return result;
57 }
58 }
59 }
60}
61
62#[derive(Debug)]
63pub struct ElimStack<T, S: Stack<T>> {
64 pub(crate) inner: S,
65 pub(crate) slots: [Atomic<S::PushReq>; ELIM_SIZE],
71}
72
73impl<T, S: Stack<T>> Default for ElimStack<T, S> {
74 fn default() -> Self {
75 Self {
76 inner: Default::default(),
77 slots: Default::default(),
78 }
79 }
80}