arctic/concurrent/smr/
no_op.rs1use core::cell::Cell;
2use core::marker::PhantomData;
3use core::num::NonZeroU64;
4use core::sync::atomic::AtomicU32;
5use core::sync::atomic::Ordering;
6
7use crate::Key;
8use crate::concurrent::Smr;
9use crate::concurrent::Value;
10use crate::concurrent::smr;
11
12thread_local! {
13 static GARBAGE_LOCAL: Cell<u32> = const { Cell::new(0) };
14}
15
16static GARBAGE_GLOBAL: AtomicU32 = AtomicU32::new(0);
17
18const GARBAGE_THRESHOLD: u32 = 256;
20
21#[derive(Default)]
25pub struct NoOp;
26
27impl<K: Key, V: Value> Smr<K, V> for NoOp {
28 type Guard<'g>
29 = Guard<(), V>
30 where
31 V: 'g,
32 Self: 'g;
33
34 fn guard<'g>(&'g self, _: K::Read<'_>) -> Self::Guard<'g>
35 where
36 V: 'g,
37 {
38 Guard::default()
39 }
40
41 fn garbage(&self) -> u32 {
42 GARBAGE_GLOBAL.load(Ordering::Relaxed)
43 }
44}
45
46pub struct Guard<G, V> {
48 _guard: PhantomData<G>,
49 _value: PhantomData<V>,
50}
51
52impl<G, V> Default for Guard<G, V> {
53 fn default() -> Self {
54 Self {
55 _guard: PhantomData,
56 _value: PhantomData,
57 }
58 }
59}
60
61impl<G, V: Value> smr::Guard<V> for Guard<G, V> {
62 unsafe fn retire_node(&mut self, _bits: usize, _node: NonZeroU64) {
63 if cfg!(feature = "stat-garbage") {
64 GARBAGE_LOCAL.set(GARBAGE_LOCAL.get() + 1);
65
66 if GARBAGE_LOCAL.get() > GARBAGE_THRESHOLD {
67 GARBAGE_GLOBAL.fetch_add(GARBAGE_THRESHOLD, Ordering::Relaxed);
68 GARBAGE_LOCAL.set(0);
69 }
70 }
71 }
72
73 unsafe fn retire_value(&mut self, _value: u64) {
74 if cfg!(feature = "stat-garbage") {
75 GARBAGE_LOCAL.set(GARBAGE_LOCAL.get() + 1);
76
77 if GARBAGE_LOCAL.get() > GARBAGE_THRESHOLD {
78 GARBAGE_GLOBAL.fetch_add(GARBAGE_THRESHOLD, Ordering::Relaxed);
79 GARBAGE_LOCAL.set(0);
80 }
81 }
82 }
83}
84
85impl<G, V: Value> From<G> for Guard<G, V> {
86 #[inline]
87 fn from(_: G) -> Self {
88 Self::default()
89 }
90}