Skip to main content

god_graph/utils/
arena.rs

1//! Arena 分配器模块
2//!
3//! 提供高效的内存分配策略,支持对象复用和稳定索引
4//!
5//! ## 特性
6//!
7//! - **O(1) 分配和释放**: 使用空闲列表实现常数时间复杂度
8//! - **缓存友好**: 64 字节对齐,避免 false sharing
9//! - **稳定索引**: generation 计数防止 ABA 问题
10//! - **内存连续**: 数据连续存储,优化 CPU 缓存命中率
11//!
12//! ## 使用示例
13//!
14//! ```
15//! # fn main() {
16//! use god_gragh::utils::arena::{Arena, Slot};
17//!
18//! let mut arena = Arena::new();
19//! let (idx, generation) = arena.allocate(42);
20//! assert_eq!(arena.get(idx, generation), Some(&42));
21//!
22//! // 释放后 generation 递增
23//! arena.deallocate(idx, generation);
24//! assert!(arena.get(idx, generation).is_none()); // 旧 generation 失效
25//! # }
26//! ```
27
28use std::fmt;
29use std::marker::PhantomData;
30
31/// 缓存行大小,用于对齐优化
32#[allow(dead_code)]
33const CACHE_LINE_SIZE: usize = 64;
34
35/// 单个槽位,存储数据和 generation 计数
36///
37/// `generation` 用于检测 ABA 问题:
38/// - 每次分配时递增
39/// - 释放后索引失效,因为 generation 不匹配
40#[derive(Clone, Debug)]
41pub struct Slot<T> {
42    /// 存储的数据,None 表示槽位已释放
43    pub data: Option<T>,
44    /// 代数计数器,每次分配递增
45    pub generation: u32,
46}
47
48impl<T> Slot<T> {
49    /// 创建新槽位
50    pub fn new(data: T, generation: u32) -> Self {
51        Self {
52            data: Some(data),
53            generation,
54        }
55    }
56
57    /// 检查槽位是否被占用
58    #[inline]
59    pub fn is_occupied(&self) -> bool {
60        self.data.is_some()
61    }
62
63    /// 获取数据引用
64    #[inline]
65    pub fn data(&self) -> Option<&T> {
66        self.data.as_ref()
67    }
68
69    /// 获取可变数据引用
70    #[inline]
71    pub fn data_mut(&mut self) -> Option<&mut T> {
72        self.data.as_mut()
73    }
74
75    /// 替换数据并返回旧数据
76    #[inline]
77    pub fn replace(&mut self, new_data: T) -> Option<T> {
78        self.data.replace(new_data)
79    }
80
81    /// 清空数据
82    #[inline]
83    pub fn clear(&mut self) -> Option<T> {
84        self.data.take()
85    }
86}
87
88/// Arena 分配器
89///
90/// 特点:
91/// - O(1) 分配和释放
92/// - 内存连续,cache-friendly
93/// - 支持对象复用(通过空闲列表)
94/// - generation 计数防止 ABA 问题
95///
96/// ## 类型参数
97///
98/// - `T`: 存储的数据类型
99///
100/// ## 示例
101///
102/// ```
103/// use god_gragh::utils::arena::Arena;
104///
105/// let mut arena = Arena::with_capacity(100);
106/// let (idx, generation) = arena.allocate("hello".to_string());
107/// assert_eq!(arena.get(idx, generation), Some(&"hello".to_string()));
108/// ```
109pub struct Arena<T> {
110    /// 存储槽位
111    slots: Vec<Slot<T>>,
112    /// 空闲列表(已删除槽位的索引)
113    free_list: Vec<usize>,
114    _marker: PhantomData<T>,
115}
116
117impl<T> fmt::Debug for Arena<T> {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        f.debug_struct("Arena")
120            .field("len", &self.len())
121            .field("capacity", &self.capacity())
122            .field("free_list_len", &self.free_list.len())
123            .finish()
124    }
125}
126
127impl<T> Arena<T> {
128    /// 创建新的 Arena
129    pub fn new() -> Self {
130        Self {
131            slots: Vec::new(),
132            free_list: Vec::new(),
133            _marker: PhantomData,
134        }
135    }
136
137    /// 创建预分配容量的 Arena
138    pub fn with_capacity(capacity: usize) -> Self {
139        Self {
140            slots: Vec::with_capacity(capacity),
141            free_list: Vec::with_capacity(capacity),
142            _marker: PhantomData,
143        }
144    }
145
146    /// 分配新对象,返回 (索引,generation)
147    ///
148    /// ## 复杂度
149    ///
150    /// - 时间:O(1) 摊销
151    /// - 空间:O(1)
152    #[inline]
153    pub fn allocate(&mut self, value: T) -> (usize, u32) {
154        if let Some(index) = self.free_list.pop() {
155            // 复用空闲槽位
156            let slot = &mut self.slots[index];
157            let new_generation = slot.generation.wrapping_add(1);
158            *slot = Slot::new(value, new_generation);
159            (index, new_generation)
160        } else {
161            // 分配新槽位
162            let index = self.slots.len();
163            let generation = 1u32;
164            self.slots.push(Slot::new(value, generation));
165            (index, generation)
166        }
167    }
168
169    /// 释放对象
170    ///
171    /// ## 参数
172    ///
173    /// - `index`: 槽位索引
174    /// - `generation`: 当前 generation,用于验证
175    ///
176    /// ## 返回值
177    ///
178    /// - `Some(T)`: 成功释放,返回数据
179    /// - `None`: 索引无效或 generation 不匹配
180    #[inline]
181    pub fn deallocate(&mut self, index: usize, generation: u32) -> Option<T> {
182        if index >= self.slots.len() {
183            return None;
184        }
185
186        let slot = &mut self.slots[index];
187        if slot.generation != generation {
188            return None; // generation 不匹配
189        }
190
191        let value = slot.data.take()?;
192        self.free_list.push(index);
193        Some(value)
194    }
195
196    /// 获取对象引用
197    ///
198    /// ## 参数
199    ///
200    /// - `index`: 槽位索引
201    /// - `generation`: 用于验证的 generation
202    #[inline]
203    pub fn get(&self, index: usize, generation: u32) -> Option<&T> {
204        self.slots
205            .get(index)
206            .filter(|slot| slot.generation == generation && slot.is_occupied())
207            .and_then(|slot| slot.data())
208    }
209
210    /// 获取对象可变引用
211    #[inline]
212    pub fn get_mut(&mut self, index: usize, generation: u32) -> Option<&mut T> {
213        self.slots
214            .get_mut(index)
215            .filter(|slot| slot.generation == generation && slot.is_occupied())
216            .and_then(|slot| slot.data_mut())
217    }
218
219    /// 检查索引是否有效
220    #[inline]
221    pub fn is_valid(&self, index: usize, generation: u32) -> bool {
222        self.slots
223            .get(index)
224            .is_some_and(|slot| slot.generation == generation && slot.is_occupied())
225    }
226
227    /// 获取槽位引用(用于高级操作)
228    #[inline]
229    pub fn get_slot(&self, index: usize) -> Option<&Slot<T>> {
230        self.slots.get(index)
231    }
232
233    /// 获取槽位可变引用
234    #[inline]
235    pub fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot<T>> {
236        self.slots.get_mut(index)
237    }
238
239    /// 清空 Arena,但不释放内存
240    #[inline]
241    pub fn clear(&mut self) {
242        for slot in &mut self.slots {
243            slot.data = None;
244        }
245        self.free_list.clear();
246        for i in 0..self.slots.len() {
247            self.free_list.push(i);
248        }
249    }
250
251    /// 完全清空 Arena,释放所有内存
252    #[inline]
253    pub fn drain(&mut self) {
254        self.slots.clear();
255        self.free_list.clear();
256    }
257
258    /// 获取已分配对象数量
259    #[inline]
260    pub fn len(&self) -> usize {
261        self.slots.len() - self.free_list.len()
262    }
263
264    /// 检查是否为空
265    #[inline]
266    pub fn is_empty(&self) -> bool {
267        self.len() == 0
268    }
269
270    /// 获取总容量(包括空闲槽位)
271    #[inline]
272    pub fn capacity(&self) -> usize {
273        self.slots.capacity()
274    }
275
276    /// 获取槽位总数
277    #[inline]
278    pub fn num_slots(&self) -> usize {
279        self.slots.len()
280    }
281
282    /// 获取空闲槽位数量
283    #[inline]
284    pub fn num_free(&self) -> usize {
285        self.free_list.len()
286    }
287
288    /// 预分配容量
289    #[inline]
290    pub fn reserve(&mut self, additional: usize) {
291        self.slots.reserve(additional);
292        self.free_list.reserve(additional);
293    }
294
295    /// 压缩空闲列表,回收内存
296    ///
297    /// 当空闲列表过大时调用,可以减少内存占用
298    pub fn shrink_to_fit(&mut self) {
299        self.free_list.shrink_to_fit();
300        self.slots.shrink_to_fit();
301    }
302
303    /// 迭代所有已分配的槽位
304    pub fn iter(&self) -> impl Iterator<Item = (usize, u32, &T)> {
305        self.slots.iter().enumerate().filter_map(|(idx, slot)| {
306            if slot.is_occupied() {
307                Some((idx, slot.generation, slot.data.as_ref().unwrap()))
308            } else {
309                None
310            }
311        })
312    }
313
314    /// 迭代所有槽位(包括空闲的)
315    pub fn iter_all(&self) -> impl Iterator<Item = (usize, &Slot<T>)> {
316        self.slots.iter().enumerate()
317    }
318}
319
320impl<T> Default for Arena<T> {
321    fn default() -> Self {
322        Self::new()
323    }
324}
325
326#[cfg(test)]
327mod tests {
328    use super::*;
329
330    #[test]
331    fn test_arena_allocate() {
332        let mut arena = Arena::new();
333        let (idx, generation) = arena.allocate(42);
334        assert_eq!(arena.get(idx, generation), Some(&42));
335        assert_eq!(generation, 1);
336    }
337
338    #[test]
339    fn test_arena_deallocate() {
340        let mut arena = Arena::new();
341        let (idx, generation) = arena.allocate(42);
342        let value = arena.deallocate(idx, generation);
343        assert_eq!(value, Some(42));
344        assert_eq!(arena.get(idx, generation), None);
345    }
346
347    #[test]
348    fn test_arena_reuse() {
349        let mut arena = Arena::new();
350        let (idx1, gen1) = arena.allocate(1);
351        let _ = arena.deallocate(idx1, gen1);
352        let (idx2, gen2) = arena.allocate(2);
353
354        // idx2 应该复用 idx1 的槽位
355        assert_eq!(idx2, idx1);
356        // generation 应该递增
357        assert_eq!(gen2, gen1 + 1);
358        assert!(arena.get(idx2, gen2).is_some());
359        assert!(arena.get(idx2, gen1).is_none());
360    }
361
362    #[test]
363    fn test_arena_is_valid() {
364        let mut arena = Arena::new();
365        let (idx, generation) = arena.allocate(42);
366
367        assert!(arena.is_valid(idx, generation));
368        assert!(!arena.is_valid(idx, generation + 1)); // generation 不匹配
369        assert!(!arena.is_valid(idx + 1, generation)); // 索引越界
370
371        arena.deallocate(idx, generation);
372        assert!(!arena.is_valid(idx, generation)); // 已释放
373    }
374
375    #[test]
376    fn test_arena_len_and_capacity() {
377        let mut arena = Arena::with_capacity(10);
378        assert_eq!(arena.len(), 0);
379        assert!(arena.is_empty());
380        assert!(arena.capacity() >= 10);
381
382        let (idx, generation) = arena.allocate(1);
383        assert_eq!(arena.len(), 1);
384        assert!(!arena.is_empty());
385
386        arena.deallocate(idx, generation);
387        assert_eq!(arena.len(), 0);
388    }
389
390    #[test]
391    fn test_arena_clear() {
392        let mut arena = Arena::new();
393        let (idx1, _) = arena.allocate(1);
394        let (idx2, _) = arena.allocate(2);
395
396        arena.clear();
397
398        assert!(arena.is_empty());
399        assert!(!arena.is_valid(idx1, 1));
400        assert!(!arena.is_valid(idx2, 1));
401    }
402
403    #[test]
404    fn test_arena_iter() {
405        let mut arena = Arena::new();
406        let (idx1, gen1) = arena.allocate(1);
407        let (idx2, gen2) = arena.allocate(2);
408        let (idx3, gen3) = arena.allocate(3);
409
410        arena.deallocate(idx2, gen2);
411
412        let items: Vec<_> = arena.iter().collect();
413        assert_eq!(items.len(), 2);
414        assert!(items
415            .iter()
416            .any(|(i, g, v)| *i == idx1 && *g == gen1 && **v == 1));
417        assert!(items
418            .iter()
419            .any(|(i, g, v)| *i == idx3 && *g == gen3 && **v == 3));
420    }
421
422    #[test]
423    fn test_arena_generation_wrap() {
424        let mut arena = Arena::new();
425        let (idx, mut generation) = arena.allocate(42);
426
427        // 模拟多次分配/释放,测试 generation 回绕
428        for _ in 0..10 {
429            arena.deallocate(idx, generation);
430            let (_, new_generation) = arena.allocate(100);
431            generation = new_generation;
432        }
433
434        // 仍然可以正常访问
435        assert!(arena.is_valid(idx, generation));
436    }
437
438    #[test]
439    fn test_arena_get_mut() {
440        let mut arena = Arena::new();
441        let (idx, generation) = arena.allocate(42);
442
443        if let Some(val) = arena.get_mut(idx, generation) {
444            *val = 100;
445        }
446
447        assert_eq!(arena.get(idx, generation), Some(&100));
448    }
449
450    #[test]
451    fn test_arena_with_capacity() {
452        let mut arena = Arena::<i32>::with_capacity(100);
453        assert!(arena.is_empty());
454        assert!(arena.capacity() >= 100);
455
456        // 预分配后应该不需要重新分配
457        for i in 0..100 {
458            arena.allocate(i);
459        }
460        assert_eq!(arena.len(), 100);
461    }
462}