use libc;
use std::cmp;
use std::mem;
use super::error::ArrowError;
use super::memory::{allocate_aligned, free_aligned};
pub trait MemoryPool {
fn allocate(&self, size: usize) -> Result<*const u8, ArrowError>;
fn reallocate(
&self,
old_size: usize,
new_size: usize,
pointer: *const u8,
) -> Result<*const u8, ArrowError>;
fn free(&self, ptr: *const u8);
}
#[allow(dead_code)]
struct LibcMemoryPool;
impl MemoryPool for LibcMemoryPool {
fn allocate(&self, size: usize) -> Result<*const u8, ArrowError> {
allocate_aligned(size as i64)
}
fn reallocate(
&self,
old_size: usize,
new_size: usize,
pointer: *const u8,
) -> Result<*const u8, ArrowError> {
unsafe {
let old_src = mem::transmute::<*const u8, *mut libc::c_void>(pointer);
let result = self.allocate(new_size)?;
let dst = mem::transmute::<*const u8, *mut libc::c_void>(result);
libc::memcpy(dst, old_src, cmp::min(old_size, new_size));
free_aligned(pointer);
Ok(result)
}
}
fn free(&self, ptr: *const u8) {
free_aligned(ptr)
}
}
#[cfg(test)]
mod tests {
use super::*;
const ALIGNMENT: usize = 64;
#[test]
fn test_allocate() {
let memory_pool = LibcMemoryPool {};
for _ in 0..10 {
let p = memory_pool.allocate(1024).unwrap();
assert_eq!(0, (p as usize) % ALIGNMENT);
memory_pool.free(p);
}
}
#[test]
fn test_reallocate() {
let memory_pool = LibcMemoryPool {};
for _ in 0..10 {
let p1 = memory_pool.allocate(1024).unwrap();
let p2 = memory_pool.reallocate(1024, 2048, p1).unwrap();
assert_eq!(0, (p1 as usize) % ALIGNMENT);
assert_eq!(0, (p2 as usize) % ALIGNMENT);
memory_pool.free(p2);
}
}
}