Skip to main content

customizable_buddy/
linked_list.rs

1use crate::{BuddyCollection, BuddyLine, OligarchyCollection, Order};
2use core::{fmt, ptr::NonNull};
3
4/// 侵入式链表伙伴行。
5///
6/// 使用单向链表管理空闲内存块,适合管理小块内存。
7/// 不支持对齐分配,时间复杂度为 O(n)。
8pub struct LinkedListBuddy {
9    /// 空闲链表头节点。
10    free_list: Node,
11    /// 当前阶数,用于指针和索引的转换。
12    order: Order,
13}
14
15/// 必须实现 [`Send`] 才能加锁。
16unsafe impl Send for LinkedListBuddy {}
17
18impl BuddyLine for LinkedListBuddy {
19    const INTRUSIVE_META_SIZE: usize = core::mem::size_of::<Node>();
20
21    const EMPTY: Self = Self {
22        free_list: Node { next: None },
23        order: Order::new(0),
24    };
25
26    #[inline]
27    fn init(&mut self, order: usize, _base: usize) {
28        self.order = Order::new(order);
29    }
30
31    fn take(&mut self, _idx: usize) -> bool {
32        todo!("not efficient")
33    }
34}
35
36impl OligarchyCollection for LinkedListBuddy {
37    #[inline]
38    fn take_any(&mut self, align_order: usize, count: usize) -> Option<usize> {
39        if count > 1 || align_order > 0 {
40            // TODO 不支持
41            None
42        } else {
43            // 直接从中删除一个节点
44            self.free_list
45                .take_any()
46                .map(|ptr| self.order.ptr_to_idx(ptr))
47        }
48    }
49
50    // 向头结点处插入一个节点
51    #[inline]
52    fn put(&mut self, idx: usize) {
53        let ptr = self.order.idx_to_ptr(idx).expect("block address is null");
54        self.free_list.insert_unordered(ptr);
55    }
56}
57
58impl BuddyCollection for LinkedListBuddy {
59    #[inline]
60    fn take_any(&mut self, align_order: usize) -> Option<usize> {
61        if align_order != 0 {
62            // TODO 需要支持对齐吗?没效率,似乎没必要
63            None
64        } else {
65            self.free_list
66                .take_any()
67                .map(|ptr| self.order.ptr_to_idx(ptr))
68        }
69    }
70
71    // 向对应位置插入一个新的元素
72    fn put(&mut self, idx: usize) -> Option<usize> {
73        // 伙伴和当前结点存在链表的同一个位置。
74        let node = self.order.idx_to_ptr(idx).expect("block address is null");
75        // buddy序号为 0 时地址为空指针,不可能在空闲链表中,跳过合并。
76        let Some(buddy) = self.order.idx_to_ptr(idx ^ 1) else {
77            self.free_list.insert_unordered(node);
78            return None;
79        };
80        if self.free_list.insert(node, buddy) {
81            None
82        } else {
83            // 插入失败说明伙伴已碰头
84            Some(idx >> 1)
85        }
86    }
87}
88
89impl fmt::Debug for LinkedListBuddy {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        write!(f, "[")?;
92        let mut cursor = &self.free_list;
93        while let Some(next) = cursor.next {
94            write!(f, "{:#x}, ", self.order.ptr_to_idx(next))?;
95            cursor = unsafe { next.as_ref() };
96        }
97        write!(f, "]")
98    }
99}
100
101/// 链表节点。
102///
103/// 侵入式链表节点,直接存储在空闲内存块中。
104#[repr(transparent)]
105struct Node {
106    /// 下一个节点的指针。
107    next: Option<NonNull<Node>>,
108}
109
110impl Node {
111    /// 插入结点,如果插入成功返回 `true`。
112    /// 如果目标结点存在,则返回 `false`,且存在的结点也被移除。
113    ///
114    /// # Notice
115    ///
116    /// 这个函数可以尾递归的,但 Rust 并不支持优化尾递归。
117    #[inline]
118    fn insert(&mut self, mut node: NonNull<Node>, buddy: NonNull<Node>) -> bool {
119        let mut cursor = self;
120        loop {
121            if let Some(mut next) = cursor.next {
122                use core::cmp::Ordering::*;
123                match next.cmp(&buddy) {
124                    // 新结点更大,找下一个
125                    Less => cursor = unsafe { next.as_mut() },
126                    // 相等,移除这一个
127                    Equal => {
128                        cursor.next = unsafe { next.as_ref().next };
129                        unsafe { node.as_mut() }.next = None;
130                        break false;
131                    }
132                    // 新结点更小,插入
133                    Greater => {
134                        cursor.next = Some(node);
135                        unsafe { node.as_mut() }.next = Some(next);
136                        break true;
137                    }
138                }
139            } else {
140                // 没有下一个,插入
141                cursor.next = Some(node);
142                unsafe { node.as_mut() }.next = None;
143                break true;
144            }
145        }
146    }
147
148    /// 直接在头结点插入。
149    #[inline]
150    fn insert_unordered(&mut self, mut node: NonNull<Node>) {
151        unsafe { node.as_mut() }.next = self.next.replace(node);
152    }
153
154    /// 直接取下头结点。
155    #[inline]
156    fn take_any(&mut self) -> Option<NonNull<Node>> {
157        let root = self.next;
158        self.next = root.and_then(|node| unsafe { node.as_ref().next });
159        root
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    // 为测试分配一些内存作为节点存储
168    #[repr(C, align(16))]
169    struct TestMemory {
170        data: [u8; 256],
171    }
172
173    #[test]
174    fn test_empty() {
175        let list = LinkedListBuddy::EMPTY;
176        assert!(list.free_list.next.is_none());
177    }
178
179    #[test]
180    fn test_init() {
181        let mut list = LinkedListBuddy::EMPTY;
182        list.init(3, 0);
183        // order 应该被设置为 3
184        assert_eq!(list.order.0, 3);
185    }
186
187    #[test]
188    fn test_insert_unordered() {
189        let mut list = LinkedListBuddy::EMPTY;
190        list.init(4, 0); // order=4
191
192        // 使用一个固定地址模拟节点
193        let mut memory = TestMemory { data: [0; 256] };
194        let node_ptr = NonNull::new(memory.data.as_mut_ptr().cast::<Node>()).unwrap();
195
196        // 将指针转换为索引,然后 put
197        let idx = list.order.ptr_to_idx(node_ptr);
198        OligarchyCollection::put(&mut list, idx);
199
200        // 链表不为空
201        assert!(list.free_list.next.is_some());
202    }
203
204    #[test]
205    fn test_take_and_put_buddy() {
206        let mut list = LinkedListBuddy::EMPTY;
207        list.init(4, 0); // order=4
208
209        // 使用一个固定地址模拟节点
210        let mut memory = TestMemory { data: [0; 256] };
211        let node_ptr = NonNull::new(memory.data.as_mut_ptr().cast::<Node>()).unwrap();
212
213        // 将指针转换为索引,然后 put
214        let idx = list.order.ptr_to_idx(node_ptr);
215        OligarchyCollection::put(&mut list, idx);
216
217        // 可以成功取出
218        let taken_idx = OligarchyCollection::take_any(&mut list, 0, 1);
219        assert_eq!(taken_idx, Some(idx));
220    }
221
222    #[test]
223    fn test_buddy_merge() {
224        let mut list = LinkedListBuddy::EMPTY;
225        list.init(4, 0); // order=4
226
227        // 使用两个地址作为伙伴节点(地址差为 1<<4 = 16)
228        let mut memory = TestMemory { data: [0; 256] };
229        let base = memory.data.as_mut_ptr() as usize;
230        // 确保 idx0 是偶数,这样 idx0 和 idx0^1 才是伙伴
231        let ptr0 = (base + 15) & !15; // 对齐到 16
232
233        // 转换为索引
234        let idx0 = ptr0 >> 4;
235
236        // 确保 idx0 是偶数
237        let idx0 = idx0 & !1; // 清除最低位
238        let idx1 = idx0 ^ 1; // 伙伴索引
239
240        // 先放入 idx0
241        OligarchyCollection::put(&mut list, idx0);
242        // 再放入 idx1(伙伴是 idx0),应该会触发合并
243        let result = BuddyCollection::put(&mut list, idx1);
244        // 应该触发合并,返回父节点索引 (idx0 >> 1)
245        assert_eq!(result, Some(idx0 >> 1));
246    }
247
248    #[test]
249    fn test_buddy_collection_take_any() {
250        let mut list = LinkedListBuddy::EMPTY;
251        list.init(0, 0);
252
253        // 空链表应该返回 None
254        assert_eq!(BuddyCollection::take_any(&mut list, 0), None);
255
256        // 不支持对齐
257        assert_eq!(BuddyCollection::take_any(&mut list, 1), None);
258    }
259
260    #[test]
261    fn test_oligarchy_collection_take_any() {
262        let mut list = LinkedListBuddy::EMPTY;
263        list.init(0, 0);
264
265        // 不支持多个块
266        assert_eq!(OligarchyCollection::take_any(&mut list, 0, 2), None);
267        // 不支持对齐
268        assert_eq!(OligarchyCollection::take_any(&mut list, 1, 1), None);
269    }
270
271    #[test]
272    fn test_node_insert() {
273        // 测试 Node::insert 方法
274        let mut head = Node { next: None };
275
276        let mut memory = TestMemory { data: [0; 256] };
277        let ptr1 = NonNull::new(memory.data.as_mut_ptr().cast::<Node>()).unwrap();
278        let ptr2 = NonNull::new(memory.data.as_mut_ptr().wrapping_add(16).cast::<Node>()).unwrap();
279        let ptr3 = NonNull::new(memory.data.as_mut_ptr().wrapping_add(32).cast::<Node>()).unwrap();
280
281        // 插入第一个节点
282        head.insert_unordered(ptr1);
283        assert!(head.next.is_some());
284
285        // 插入第二个节点
286        head.insert_unordered(ptr2);
287
288        // 使用 insert 尝试找到伙伴(不存在的伙伴)
289        let buddy = NonNull::new(memory.data.as_mut_ptr().wrapping_add(64).cast::<Node>()).unwrap();
290        assert!(head.insert(ptr3, buddy));
291    }
292
293    #[test]
294    fn test_node_take_any() {
295        let mut head = Node { next: None };
296
297        let mut memory = TestMemory { data: [0; 256] };
298        let ptr = NonNull::new(memory.data.as_mut_ptr().cast::<Node>()).unwrap();
299
300        head.insert_unordered(ptr);
301
302        // 取出一个节点
303        let taken = head.take_any();
304        assert!(taken.is_some());
305
306        // 再次取出应该返回 None
307        assert!(head.take_any().is_none());
308    }
309}