#![no_std]
extern crate bitvec;
use bitvec::prelude::*;
pub struct RawBuddies<T> {
num: usize,
data: *mut T,
bits: *mut u8,
}
impl<T> RawBuddies<T> {
pub unsafe fn new(num: usize, data: *mut T, bits: *mut u8) -> Self {
Self {
num,
data,
bits,
}
}
pub fn can_allocate(&self, n: usize) -> bool {
assert!(n < self.num);
self.buddymap_ref(n).any()
}
pub fn allocate(&mut self, n: usize) -> Option<(*mut T, usize)> {
assert!(n < self.num);
let pos = self.buddymap_ref(n).iter().position(|s| s)?;
self.set_network(n, pos, true);
Some((unsafe { self.data.add(pos << n) }, pos))
}
pub fn free(&mut self, n: usize, pos: usize) {
assert!(n < self.num);
assert!(pos < (1usize << (self.num - n - 1)));
assert!(self.buddymap_ref(n)[pos]);
unsafe { core::ptr::drop_in_place(self.data.add(pos << n)); }
self.set_network(n, pos, false);
}
fn buddymap_ref(&self, n: usize) -> &BitSlice {
assert!(n < self.num);
let bits: &BitSlice = unsafe {
core::slice::from_raw_parts(self.bits, 1usize << self.num)
}.into();
&bits[
(1usize << self.num) - (1usize << (self.num - n))
.. (1usize << self.num) - (1usize << (self.num - n - 1))
]
}
fn buddymap_mut(&mut self, n: usize) -> &mut BitSlice {
assert!(n < self.num);
let bits: &mut BitSlice = unsafe {
core::slice::from_raw_parts_mut(self.bits, 1usize << self.num)
}.into();
&mut bits[
(1usize << self.num) - (1usize << (self.num - n))
.. (1usize << self.num) - (1usize << (self.num - n - 1))
]
}
fn set_network(&mut self, n: usize, i: usize, v: bool) {
assert!(n < self.num);
assert!(i < (1 << n));
for b in 0..n {
self.buddymap_mut(b)[i << (n-b) .. (i+1) << (n-b)].set_all(v);
}
if v {
for b in n .. self.num {
let map = self.buddymap_mut(b);
if map[i >> (b-n)] {
break;
}
map.set(i >> (b-n), true);
}
} else {
for b in n .. self.num {
let map = self.buddymap_mut(b);
map.set(i >> (b-n), false);
if map[(i >> (b-n)) ^ 1] {
break;
}
}
}
}
}