Skip to main content

atom_engine/
pool.rs

1use std::fmt;
2pub struct MemoryPool {
3    chunk_size: usize,
4    max_chunks: usize,
5}
6
7impl MemoryPool {
8    pub fn new(chunk_size: usize, max_chunks: usize) -> Self {
9        MemoryPool {
10            chunk_size: chunk_size.max(64),
11            max_chunks: max_chunks.max(1),
12        }
13    }
14
15    pub fn chunk_size(&self) -> usize {
16        self.chunk_size
17    }
18
19    pub fn max_chunks(&self) -> usize {
20        self.max_chunks
21    }
22}
23
24impl Default for MemoryPool {
25    fn default() -> Self {
26        Self::new(4096, 16)
27    }
28}
29
30impl fmt::Debug for MemoryPool {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        f.debug_struct("MemoryPool")
33            .field("chunk_size", &self.chunk_size)
34            .field("max_chunks", &self.max_chunks)
35            .finish()
36    }
37}
38
39pub struct PooledString {
40    data: Vec<u8>,
41}
42
43impl PooledString {
44    pub fn new() -> Self {
45        PooledString { data: Vec::new() }
46    }
47
48    pub fn with_capacity(capacity: usize) -> Self {
49        PooledString {
50            data: Vec::with_capacity(capacity),
51        }
52    }
53
54    pub fn from_string(s: String) -> Self {
55        PooledString {
56            data: s.into_bytes(),
57        }
58    }
59
60    pub fn as_str(&self) -> &str {
61        unsafe { std::str::from_utf8_unchecked(&self.data) }
62    }
63
64    pub fn as_bytes(&self) -> &[u8] {
65        &self.data
66    }
67
68    pub fn push_str(&mut self, s: &str) {
69        self.data.extend(s.as_bytes());
70    }
71
72    pub fn push(&mut self, c: char) {
73        self.data.extend(c.encode_utf8(&mut [0u8; 4]).as_bytes());
74    }
75
76    pub fn len(&self) -> usize {
77        self.data.len()
78    }
79
80    pub fn is_empty(&self) -> bool {
81        self.data.is_empty()
82    }
83
84    pub fn clear(&mut self) {
85        self.data.clear();
86    }
87
88    pub fn capacity(&self) -> usize {
89        self.data.capacity()
90    }
91
92    pub fn reserve(&mut self, additional: usize) {
93        self.data.reserve(additional);
94    }
95
96    pub fn truncate(&mut self, len: usize) {
97        self.data.truncate(len);
98    }
99}
100
101impl Default for PooledString {
102    fn default() -> Self {
103        Self::new()
104    }
105}
106
107impl fmt::Debug for PooledString {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        f.debug_struct("PooledString")
110            .field("len", &self.len())
111            .field("capacity", &self.capacity())
112            .finish()
113    }
114}
115
116impl Clone for PooledString {
117    fn clone(&self) -> Self {
118        PooledString {
119            data: self.data.clone(),
120        }
121    }
122}
123
124impl From<String> for PooledString {
125    fn from(s: String) -> Self {
126        PooledString::from_string(s)
127    }
128}
129
130impl From<&str> for PooledString {
131    fn from(s: &str) -> Self {
132        PooledString::from_string(s.to_string())
133    }
134}
135
136impl std::ops::Deref for PooledString {
137    type Target = str;
138
139    fn deref(&self) -> &Self::Target {
140        self.as_str()
141    }
142}
143
144pub struct StringPool {
145    strings: Vec<PooledString>,
146    #[allow(dead_code)]
147    max_size: usize,
148}
149
150impl StringPool {
151    pub fn new() -> Self {
152        StringPool {
153            strings: Vec::new(),
154            max_size: 1024,
155        }
156    }
157
158    pub fn with_max_size(max_size: usize) -> Self {
159        StringPool {
160            strings: Vec::new(),
161            max_size,
162        }
163    }
164
165    pub fn store(&mut self, s: &str) -> PooledString {
166        PooledString::from_string(s.to_string())
167    }
168
169    pub fn get_or_insert(&mut self, s: &str) -> PooledString {
170        self.store(s)
171    }
172
173    pub fn clear(&mut self) {
174        self.strings.clear();
175    }
176
177    pub fn len(&self) -> usize {
178        self.strings.len()
179    }
180
181    pub fn is_empty(&self) -> bool {
182        self.strings.is_empty()
183    }
184
185    pub fn total_capacity(&self) -> usize {
186        self.strings.iter().map(|s| s.capacity()).sum()
187    }
188}
189
190impl Default for StringPool {
191    fn default() -> Self {
192        Self::new()
193    }
194}
195
196impl fmt::Debug for StringPool {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        f.debug_struct("StringPool")
199            .field("len", &self.len())
200            .field("total_capacity", &self.total_capacity())
201            .finish()
202    }
203}
204
205#[allow(dead_code)]
206pub mod pool_alloc {
207    use std::sync::atomic::{AtomicUsize, Ordering};
208
209    static ALLOC_COUNT: AtomicUsize = AtomicUsize::new(0);
210    static ALLOC_COUNT_MAX: AtomicUsize = AtomicUsize::new(0);
211
212    pub fn get_alloc_count() -> usize {
213        ALLOC_COUNT.load(Ordering::Relaxed)
214    }
215
216    pub fn get_max_alloc_count() -> usize {
217        ALLOC_COUNT_MAX.load(Ordering::Relaxed)
218    }
219
220    pub fn reset_count() {
221        ALLOC_COUNT.store(0, Ordering::Relaxed);
222    }
223
224    pub fn record_allocation(size: usize) {
225        let current = ALLOC_COUNT.fetch_add(size, Ordering::Relaxed);
226        let max = ALLOC_COUNT_MAX.load(Ordering::Relaxed);
227        if current > max {
228            ALLOC_COUNT_MAX.store(current, Ordering::Relaxed);
229        }
230    }
231
232    pub fn record_deallocation(size: usize) {
233        ALLOC_COUNT.fetch_sub(size, Ordering::Relaxed);
234    }
235}