use alloc::heap;
use std::mem;
use std::intrinsics::abort;
use std::io::{self, Write};
use std::ptr;
use ll::limb::Limb;
use ll::limb_ptr::LimbsMut;
pub unsafe fn allocate_bytes(size: usize) -> *mut u8 {
let ret = heap::allocate(size, mem::align_of::<usize>());
if ret.is_null() {
let _ = writeln!(io::stderr(), "Failed to allocate memory (size={})", size);
abort();
}
ptr::write_bytes(ret, 0, size);
ret
}
pub unsafe fn deallocate_bytes(ptr: *mut u8, size: usize) {
heap::deallocate(ptr, size, mem::align_of::<usize>());
}
pub struct TmpAllocator {
mark: *mut Marker
}
struct Marker {
next: *mut Marker,
size: usize
}
impl TmpAllocator {
pub fn new() -> TmpAllocator {
TmpAllocator {
mark: ptr::null_mut()
}
}
pub unsafe fn allocate_bytes(&mut self, size: usize) -> *mut u8 {
let size = size + mem::size_of::<Marker>();
let ptr = allocate_bytes(size);
let mark = ptr as *mut Marker;
(*mark).size = size;
(*mark).next = self.mark;
self.mark = mark;
ptr.offset(mem::size_of::<Marker>() as isize)
}
pub unsafe fn allocate(&mut self, n: usize) -> LimbsMut {
let ptr = self.allocate_bytes(n * mem::size_of::<Limb>()) as *mut Limb;
LimbsMut::new(ptr, 0, n as i32)
}
pub unsafe fn allocate_2(&mut self, n1: usize, n2: usize) -> (LimbsMut, LimbsMut) {
let mut x = self.allocate(n1 + n2);
let mut y = x.offset(n1 as isize);
(LimbsMut::new(&mut *x, 0, n1 as i32),
LimbsMut::new(&mut *y, 0, n2 as i32))
}
}
impl Drop for TmpAllocator {
fn drop(&mut self) {
unsafe {
let mut next;
let mut mark = self.mark;
while !mark.is_null() {
next = (*mark).next;
let size = (*mark).size;
deallocate_bytes(mark as *mut u8, size);
mark = next;
}
}
}
}