style/use_counters/
mod.rs1use crate::properties::{property_counts, CountedUnknownProperty, NonCustomPropertyId};
8use std::sync::atomic::{AtomicUsize, Ordering};
9
10#[cfg(target_pointer_width = "64")]
11const BITS_PER_ENTRY: usize = 64;
12
13#[cfg(target_pointer_width = "32")]
14const BITS_PER_ENTRY: usize = 32;
15
16#[derive(Debug, Default)]
18pub struct CountedUnknownPropertyUseCounters {
19 storage:
20 [AtomicUsize; (property_counts::COUNTED_UNKNOWN + BITS_PER_ENTRY - 1) / BITS_PER_ENTRY],
21}
22
23#[derive(Debug, Default)]
25pub struct NonCustomPropertyUseCounters {
26 storage: [AtomicUsize; (property_counts::NON_CUSTOM + BITS_PER_ENTRY - 1) / BITS_PER_ENTRY],
27}
28
29#[derive(Copy, Clone, Debug)]
31#[repr(u32)]
32pub enum CustomUseCounter {
33 MaybeHasPathBaseUriDependency = 0,
35 MaybeHasFullBaseUriDependency,
37 Last,
39}
40
41impl CustomUseCounter {
42 #[inline]
43 fn bit(self) -> usize {
44 self as usize
45 }
46}
47
48#[derive(Debug, Default)]
50pub struct CustomUseCounters {
51 storage:
52 [AtomicUsize; ((CustomUseCounter::Last as usize) + BITS_PER_ENTRY - 1) / BITS_PER_ENTRY],
53}
54
55macro_rules! use_counters_methods {
56 ($id: ident) => {
57 #[inline(always)]
60 fn bucket_and_pattern(id: $id) -> (usize, usize) {
61 let bit = id.bit();
62 let bucket = bit / BITS_PER_ENTRY;
63 let bit_in_bucket = bit % BITS_PER_ENTRY;
64 (bucket, 1 << bit_in_bucket)
65 }
66
67 #[inline]
69 pub fn record(&self, id: $id) {
70 let (bucket, pattern) = Self::bucket_and_pattern(id);
71 let bucket = &self.storage[bucket];
72 bucket.fetch_or(pattern, Ordering::Relaxed);
73 }
74
75 #[inline]
78 pub fn recorded(&self, id: $id) -> bool {
79 let (bucket, pattern) = Self::bucket_and_pattern(id);
80 self.storage[bucket].load(Ordering::Relaxed) & pattern != 0
81 }
82
83 #[inline]
85 fn merge(&self, other: &Self) {
86 for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) {
87 bucket.fetch_or(other_bucket.load(Ordering::Relaxed), Ordering::Relaxed);
88 }
89 }
90 };
91}
92
93impl CountedUnknownPropertyUseCounters {
94 use_counters_methods!(CountedUnknownProperty);
95}
96
97impl NonCustomPropertyUseCounters {
98 use_counters_methods!(NonCustomPropertyId);
99}
100
101impl CustomUseCounters {
102 use_counters_methods!(CustomUseCounter);
103}
104
105#[derive(Debug, Default)]
107pub struct UseCounters {
108 pub non_custom_properties: NonCustomPropertyUseCounters,
111 pub counted_unknown_properties: CountedUnknownPropertyUseCounters,
113 pub custom: CustomUseCounters,
115}
116
117impl UseCounters {
118 #[inline]
122 pub fn merge(&self, other: &Self) {
123 self.non_custom_properties
124 .merge(&other.non_custom_properties);
125 self.counted_unknown_properties
126 .merge(&other.counted_unknown_properties);
127 self.custom.merge(&other.custom);
128 }
129}
130
131impl Clone for UseCounters {
132 fn clone(&self) -> Self {
133 let result = Self::default();
134 result.merge(self);
135 result
136 }
137}