1use downcast_rs::{impl_downcast, Downcast};
2
3pub const FAILURE: i32 = -1;
4
5pub const MAX_HEADS: i32 = 128; const TOTAL_BITS: i32 = 32;
7const UNIT_BITS: i32 = TOTAL_BITS - 2;
8pub const MAX_UNITS: i32 = ((1 << UNIT_BITS) - 1) - MAX_HEADS - 1;
9
10const NEXT_MASK: i32 = (1 << UNIT_BITS) - 1;
11const PREV_MASK: i32 = (1 << UNIT_BITS) - 1;
12const FREE_MASK: i32 = 1 << (TOTAL_BITS - 1);
13const MULTI_MASK: i32 = 1 << (TOTAL_BITS - 1);
14const COALESC_MASK: i32 = 1 << (TOTAL_BITS - 2);
15const SIZE_MASK: i32 = (1 << UNIT_BITS) - 1;
16
17pub trait FreeList: Sync + Downcast {
18 fn head(&self) -> i32;
19 fn heads(&self) -> i32;
21 fn get_entry(&self, index: i32) -> i32;
25 fn set_entry(&mut self, index: i32, value: i32);
26
27 fn alloc(&mut self, size: i32) -> i32 {
28 let mut unit = self.head();
29 let mut s = 0;
30 while ({
31 unit = self.get_next(unit);
32 unit != self.head()
33 }) && ({
34 s = self.get_size(unit);
35 s < size
36 }) {}
37 if unit == self.head() {
49 FAILURE
50 } else {
51 self.__alloc(size, unit, s)
52 }
53 }
54
55 fn alloc_from_unit(&mut self, size: i32, unit: i32) -> i32 {
56 if self.get_free(unit) {
57 let s = self.get_size(unit);
58 if s >= size {
59 return self.__alloc(size, unit, s);
60 }
61 }
62 FAILURE
63 }
64
65 fn free(&mut self, unit: i32, return_coalesced_size: bool) -> i32 {
67 debug_assert!(!self.get_free(unit));
68 let mut freed = self.get_size(unit);
69 let left = self.get_left(unit);
70 let start = if self.is_coalescable(unit) && self.get_free(left) {
71 left
72 } else {
73 unit
74 };
75 let right = self.get_right(unit);
76 let end = if self.is_coalescable(right) && self.get_free(right) {
77 right
78 } else {
79 unit
80 };
81 if start != end {
82 self.__coalesce(start, end);
83 }
84
85 if return_coalesced_size {
86 freed = self.get_size(start);
87 }
88 self.add_to_free(start);
89
90 freed
91 }
92
93 fn size(&self, unit: i32) -> i32 {
94 self.get_size(unit)
95 }
96
97 fn initialize_heap(&mut self, units: i32, grain: i32) {
98 for i in 1..=self.heads() {
101 self.set_sentinel(-i);
102 }
103 self.set_sentinel(units);
105
106 let offset = units % grain;
108 let mut cursor = units - offset;
109 if offset > 0 {
110 self.set_size(cursor, offset);
111 self.add_to_free(cursor);
112 }
113 cursor -= grain;
114 while cursor >= 0 {
115 self.set_size(cursor, grain);
116 self.add_to_free(cursor);
117 cursor -= grain;
118 }
119 }
120
121 fn add_to_free(&mut self, unit: i32) {
122 self.set_free(unit, true);
123 let next = self.get_next(self.head());
124 self.set_next(unit, next);
125 let head = self.head();
126 self.set_next(head, unit);
127 let head = self.head();
128 self.set_prev(unit, head);
129 self.set_prev(next, unit);
130 }
131
132 fn get_right(&self, unit: i32) -> i32 {
133 unit + self.get_size(unit)
134 }
135
136 fn set_sentinel(&mut self, unit: i32) {
137 self.set_lo_entry(unit, NEXT_MASK & unit);
138 self.set_hi_entry(unit, PREV_MASK & unit);
139 }
140
141 fn get_size(&self, unit: i32) -> i32 {
142 if (self.get_hi_entry(unit) & MULTI_MASK) == MULTI_MASK {
143 self.get_hi_entry(unit + 1) & SIZE_MASK
144 } else {
145 1
146 }
147 }
148
149 fn set_size(&mut self, unit: i32, size: i32) {
150 let hi = self.get_hi_entry(unit);
151 if size > 1 {
152 self.set_hi_entry(unit, hi | MULTI_MASK);
153 self.set_hi_entry(unit + 1, MULTI_MASK | size);
154 self.set_hi_entry(unit + size - 1, MULTI_MASK | size);
155 } else {
156 self.set_hi_entry(unit, hi & !MULTI_MASK);
157 }
158 }
159
160 fn get_free(&self, unit: i32) -> bool {
161 (self.get_lo_entry(unit) & FREE_MASK) == FREE_MASK
162 }
163
164 fn set_free(&mut self, unit: i32, is_free: bool) {
165 let size;
166 let lo = self.get_lo_entry(unit);
167 if is_free {
168 self.set_lo_entry(unit, lo | FREE_MASK);
169 size = self.get_size(unit);
170 if size > 1 {
171 let lo = self.get_lo_entry(unit + size - 1);
172 self.set_lo_entry(unit + size - 1, lo | FREE_MASK);
173 }
174 } else {
175 self.set_lo_entry(unit, lo & !FREE_MASK);
176 size = self.get_size(unit);
177 if size > 1 {
178 let lo = self.get_lo_entry(unit + size - 1);
179 self.set_lo_entry(unit + size - 1, lo & !FREE_MASK);
180 }
181 }
182 }
183
184 fn get_next(&self, unit: i32) -> i32 {
185 let next = self.get_hi_entry(unit) & NEXT_MASK;
186 if next <= MAX_UNITS {
187 next
188 } else {
189 self.head()
190 }
191 }
192
193 fn set_next(&mut self, unit: i32, next: i32) {
194 debug_assert!((next >= -self.heads()) && (next <= MAX_UNITS));
195 let old_value = self.get_hi_entry(unit);
196 let new_value = (old_value & !NEXT_MASK) | (next & NEXT_MASK);
197 self.set_hi_entry(unit, new_value);
198 }
199
200 fn get_prev(&self, unit: i32) -> i32 {
202 let prev = self.get_lo_entry(unit) & PREV_MASK;
203 if prev <= MAX_UNITS {
204 prev
205 } else {
206 self.head()
207 }
208 }
209
210 fn set_prev(&mut self, unit: i32, prev: i32) {
211 debug_assert!((prev >= -self.heads()) && (prev <= MAX_UNITS));
212 let old_value = self.get_lo_entry(unit);
213 let new_value = (old_value & !PREV_MASK) | (prev & PREV_MASK);
214 self.set_lo_entry(unit, new_value);
215 }
216
217 fn get_left(&self, unit: i32) -> i32 {
219 if (self.get_hi_entry(unit - 1) & MULTI_MASK) == MULTI_MASK {
220 unit - (self.get_hi_entry(unit - 1) & SIZE_MASK)
221 } else {
222 unit - 1
223 }
224 }
225
226 fn is_coalescable(&self, unit: i32) -> bool {
227 (self.get_lo_entry(unit) & COALESC_MASK) == 0
228 }
229
230 fn clear_uncoalescable(&mut self, unit: i32) {
231 let lo = self.get_lo_entry(unit);
232 self.set_lo_entry(unit, lo & !COALESC_MASK);
233 }
234
235 fn set_uncoalescable(&mut self, unit: i32) {
236 let lo = self.get_lo_entry(unit);
237 self.set_lo_entry(unit, lo | COALESC_MASK);
238 }
239
240 fn is_multi(&self, i: i32) -> bool {
241 let hi = self.get_hi_entry(i);
242 (hi & MULTI_MASK) == MULTI_MASK
243 }
244
245 fn is_free(&self, i: i32) -> bool {
246 let lo = self.get_lo_entry(i);
247 (lo & FREE_MASK) == FREE_MASK
248 }
249
250 fn get_lo_entry(&self, unit: i32) -> i32 {
251 self.get_entry((unit + self.heads()) << 1)
252 }
253
254 fn get_hi_entry(&self, unit: i32) -> i32 {
255 self.get_entry(((unit + self.heads()) << 1) + 1)
256 }
257
258 fn set_lo_entry(&mut self, unit: i32, value: i32) {
259 let heads = self.heads();
260 self.set_entry((unit + heads) << 1, value);
261 }
262
263 fn set_hi_entry(&mut self, unit: i32, value: i32) {
264 let heads = self.heads();
265 self.set_entry(((unit + heads) << 1) + 1, value);
266 }
267
268 fn __alloc(&mut self, size: i32, unit: i32, unit_size: i32) -> i32 {
271 if unit_size >= size {
272 if unit_size > size {
273 self.__split(unit, size);
274 }
275 self.__remove_from_free(unit);
276 self.set_free(unit, false);
277 }
278 unit
279 }
280
281 fn __split(&mut self, unit: i32, size: i32) {
282 let basesize = self.get_size(unit);
283 debug_assert!(basesize > size);
284 self.set_size(unit, size);
285 self.set_size(unit + size, basesize - size);
286 self.add_to_free(unit + size);
287 }
288
289 fn __coalesce(&mut self, start: i32, end: i32) {
290 if self.get_free(end) {
291 self.__remove_from_free(end);
292 }
293 if self.get_free(start) {
294 self.__remove_from_free(start);
295 }
296 let size = self.get_size(end);
297 self.set_size(start, end - start + size);
298 }
299
300 fn __remove_from_free(&mut self, unit: i32) {
301 let next = self.get_next(unit);
302 let prev = self.get_prev(unit);
303 self.set_next(prev, next);
304 self.set_prev(next, prev);
305 }
306}
307
308impl_downcast!(FreeList);