customizable_buddy/
linked_list.rs1use crate::{BuddyCollection, BuddyLine, OligarchyCollection, Order};
2use core::{fmt, ptr::NonNull};
3
4pub struct LinkedListBuddy {
6 free_list: Node,
7 order: Order,
8}
9
10unsafe impl Send for LinkedListBuddy {}
12
13impl BuddyLine for LinkedListBuddy {
14 const INTRUSIVE_META_SIZE: usize = core::mem::size_of::<Node>();
15
16 const EMPTY: Self = Self {
17 free_list: Node { next: None },
18 order: Order::new(0),
19 };
20
21 #[inline]
22 fn init(&mut self, order: usize, _base: usize) {
23 self.order = Order::new(order);
24 }
25
26 fn take(&mut self, _idx: usize) -> bool {
27 unimplemented!("not efficient")
29 }
30}
31
32impl OligarchyCollection for LinkedListBuddy {
33 #[inline]
34 fn take_any(&mut self, align_order: usize, count: usize) -> Option<usize> {
35 if count > 1 || align_order > 0 {
36 None
38 } else {
39 self.free_list
40 .take_any()
41 .map(|ptr| self.order.ptr_to_idx(ptr))
42 }
43 }
44
45 #[inline]
46 fn put(&mut self, idx: usize) {
47 self.free_list
48 .insert_unordered(unsafe { self.order.idx_to_ptr(idx) });
49 }
50}
51
52impl BuddyCollection for LinkedListBuddy {
53 #[inline]
54 fn take_any(&mut self, align_order: usize) -> Option<usize> {
55 if align_order != 0 {
56 None
58 } else {
59 self.free_list
60 .take_any()
61 .map(|ptr| self.order.ptr_to_idx(ptr))
62 }
63 }
64
65 fn put(&mut self, idx: usize) -> Option<usize> {
66 let node = unsafe { self.order.idx_to_ptr(idx) };
68 let buddy = unsafe { self.order.idx_to_ptr(idx ^ 1) };
69 if self.free_list.insert(node, buddy) {
70 None
71 } else {
72 Some(idx >> 1)
74 }
75 }
76}
77
78impl fmt::Debug for LinkedListBuddy {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 write!(f, "[")?;
81 let mut cursor = &self.free_list;
82 while let Some(next) = cursor.next {
83 write!(f, "{:#x}, ", self.order.ptr_to_idx(next))?;
84 cursor = unsafe { next.as_ref() };
85 }
86 write!(f, "]")
87 }
88}
89
90#[repr(transparent)]
91struct Node {
92 next: Option<NonNull<Node>>,
93}
94
95impl Node {
96 #[inline]
103 fn insert(&mut self, mut node: NonNull<Node>, buddy: NonNull<Node>) -> bool {
104 let mut cursor = self;
105 loop {
106 if let Some(mut next) = cursor.next {
107 use core::cmp::Ordering::*;
108 match next.cmp(&buddy) {
109 Less => cursor = unsafe { next.as_mut() },
111 Equal => {
113 cursor.next = unsafe { next.as_ref().next };
114 unsafe { node.as_mut() }.next = None;
115 break false;
116 }
117 Greater => {
119 cursor.next = Some(node);
120 unsafe { node.as_mut() }.next = Some(next);
121 break true;
122 }
123 }
124 } else {
125 cursor.next = Some(node);
127 unsafe { node.as_mut() }.next = None;
128 break true;
129 }
130 }
131 }
132
133 #[inline]
135 fn insert_unordered(&mut self, mut node: NonNull<Node>) {
136 unsafe { node.as_mut() }.next = core::mem::replace(&mut self.next, Some(node));
137 }
138
139 #[inline]
141 fn take_any(&mut self) -> Option<NonNull<Node>> {
142 let root = self.next;
143 self.next = root.and_then(|node| unsafe { node.as_ref().next });
144 root
145 }
146}