added store

master
Avril 4 years ago
parent ba1d610d3d
commit 1f0880329a
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,7 +1,7 @@
[package] [package]
name = "malloc-array" name = "malloc-array"
description = "libc heap array allocator" description = "libc heap array allocator"
version = "1.3.3" version = "1.4.3"
authors = ["Avril <flanchan@cumallover.me>"] authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018" edition = "2018"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"

@ -9,6 +9,17 @@ extern crate jemalloc_sys;
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn from_bytes()
{
unsafe {
let heap = HeapArray::<i32>::from_bytes(&[0xff,0xff,0xff,0xff,0,0,0,0,0xff,0xff,0xff,0xff]);
assert_eq!(heap[0], -1);
assert_eq!(heap[1], 0);
assert_eq!(heap[2], -1);
}
}
#[test] #[test]
fn copy() { fn copy() {
let heap = heap![unsafe 1u16; 10]; let heap = heap![unsafe 1u16; 10];
@ -179,6 +190,7 @@ mod alloc;
mod reinterpret; mod reinterpret;
pub mod init; pub mod init;
pub use init::InitIterExt; pub use init::InitIterExt;
pub mod store;
use std::{ use std::{
ops::{ ops::{
@ -201,6 +213,7 @@ use std::{
use crate::{ use crate::{
ptr::{ ptr::{
VoidPointer, VoidPointer,
ConstVoidPointer,
}, },
}; };
@ -604,11 +617,37 @@ impl<T> HeapArray<T>
} }
} }
/// Copy memory in from a slice of bytes.
pub unsafe fn memory_from_bytes<U: AsRef<[u8]>>(&mut self, from: U) -> usize
{
let from = from.as_ref();
let size = std::cmp::min(from.len(), self.len_bytes());
ptr::memcpy(self.ptr as VoidPointer, &from[0] as *const u8 as ConstVoidPointer, size);
size
}
/// Copy memory in from a pointer to bytes.
pub unsafe fn memory_from_raw_bytes(&mut self, from: *const u8, size: usize) -> usize
{
let size = std::cmp::min(size, self.len_bytes());
ptr::memcpy(self.ptr as VoidPointer, from as *const u8 as ConstVoidPointer, size);
size
}
/// Copy memory in from a raw pointer.
pub unsafe fn memory_from_slice<U: AsRef<[T]>>(&mut self, from: U) -> usize
{
let from = from.as_ref();
let size = std::cmp::min(from.len(), self.len());
ptr::memcpy(self.ptr as VoidPointer, &from[0] as *const T as ConstVoidPointer, size * std::mem::size_of::<T>());
size
}
/// Copy memory in from a raw pointer. /// Copy memory in from a raw pointer.
pub unsafe fn memory_from_raw(&mut self, from: *const T, size: usize) -> usize pub unsafe fn memory_from_raw(&mut self, from: *const T, size: usize) -> usize
{ {
let size = std::cmp::min(size, self.len()); let size = std::cmp::min(size, self.len());
ptr::memcpy(self.ptr as VoidPointer, from as VoidPointer, size * std::mem::size_of::<T>()); ptr::memcpy(self.ptr as VoidPointer, from as *const T as ConstVoidPointer, size * std::mem::size_of::<T>());
size size
} }
@ -619,6 +658,31 @@ impl<T> HeapArray<T>
inp.memory_from_raw(from, size); inp.memory_from_raw(from, size);
inp inp
} }
/// Create a new instance with memory copied from a slice.
pub unsafe fn from_slice_copied<U: AsRef<[T]>>(from: U) -> Self
where T: Copy
{
let from = from.as_ref();
Self::from_raw_copied(&from[0] as *const T, from.len())
}
/// Create a new instance with memory bytes copied from a raw pointer.
pub unsafe fn from_raw_bytes(from: *const u8, size: usize) -> Self
{
assert_eq!(size % Self::element_size(),0,"Cannot fit T into this size.");
let mut inp = Self::new_uninit(size / Self::element_size());
inp.memory_from_raw_bytes(from, size);
inp
}
/// Create a new instance with memory bytes copied from a slice.
pub unsafe fn from_bytes<U: AsRef<[u8]>>(from: U) -> Self
{
let from = from.as_ref();
Self::from_raw_bytes(&from[0], from.len())
}
} }
impl<T, I> Index<I> for HeapArray<T> impl<T, I> Index<I> for HeapArray<T>

@ -0,0 +1,247 @@
use crate::*;
/// Statically typed pointer store. `free()`s and drops on drop.
#[derive(Debug)]
pub struct Store<T>
{
pointers: Vec<*mut T>,
}
#[cfg(test)]
mod tests
{
use super::*;
#[test]
fn store()
{
let mut store = Store::new();
unsafe {
for _a in 0..10 {
let _ptr = store.ptr(alloc::malloc(100).unwrap());
}
}
}
#[test]
fn dyn_store()
{
let mut store = DynStore::new();
unsafe {
for _a in 0..10 {
let ptr = store.ptr(alloc::malloc(4).unwrap() as *mut u32);
*ptr = 100u32;
}
}
}
#[test]
fn into_ha()
{
let mut store = Store::new();
unsafe {
for a in 0..10 {
*store.ptr(alloc::malloc(4).unwrap() as *mut u32) = a;
}
}
let ha = store.into_heap_array();
assert_eq!(ha.len(), 10);
assert_eq!(&ha[..], &[0,1,2,3,4,5,6,7,8,9]);
}
}
impl<T> Store<T>
{
/// Create a new pointer store.
pub fn new() -> Self
{
Self{pointers:Vec::new()}
}
/// Add a pointer to the store.
pub fn ptr(&mut self, ptr: *mut T) -> *mut T
{
self.pointers.push(ptr);
ptr
}
/// Remove a pointer from the store.
pub fn remove(&mut self, ptr: *mut T)
{
while let Some(i) = self.pointers.iter().position(|x| *x == ptr)
{
self.pointers.remove(i);
}
}
/// Consumes the instance and returns the pointers without freeing them.
pub fn into_raw_parts(mut self) -> Vec<*mut T>
{
std::mem::replace(&mut self.pointers, Vec::new())
}
/// Consume a vector of pointers and return a new `Store<T>`.
pub fn from_raw_parts(pointers: Vec<*mut T>) -> Self
{
Self {
pointers,
}
}
/// Free all the pointers in the store without calling their destructors (if the have any).
pub fn free(mut self)
{
for &mut x in self.pointers.iter_mut()
{
unsafe {
alloc::free(x as VoidPointer);
}
}
self.pointers.clear()
}
/// Move all data from all pointers into a new `HeapArray<T>` instance and free the old pointers.
pub fn into_heap_array(mut self) -> HeapArray<T>
{
let mut output = heap![T; self.pointers.len()];
for (mut init, old) in output.initialise().zip(std::mem::replace(&mut self.pointers, Vec::new()).into_iter())
{
unsafe {
init.put(ptr::take(old));
alloc::free(old as *mut ());
}
}
output
}
}
impl<T> std::ops::Drop for Store<T>
{
fn drop(&mut self)
{
for &mut ptr in self.pointers.iter_mut()
{
unsafe {
drop(ptr::take(ptr));
alloc::free(ptr as VoidPointer);
}
}
self.pointers.clear();
}
}
/// Dynamically typed pointer store. Frees on drop.
#[derive(Debug)]
pub struct DynStore
{
pointers: Vec<VoidPointer>,
}
impl DynStore
{
/// Create a new pointer store.
pub fn new() -> Self
{
Self{pointers:Vec::new()}
}
/// Add a pointer to the store.
pub fn ptr<T>(&mut self, ptr: *mut T) -> *mut T
{
self.pointers.push(ptr as VoidPointer);
ptr
}
/// Remove a pointer from the store.
pub fn remove<T>(&mut self, ptr: *mut T)
{
while let Some(i) = self.pointers.iter().position(|x| *x == ptr as VoidPointer)
{
self.pointers.remove(i);
}
}
/// Consumes the instance and returns the pointers without freeing them.
pub fn into_raw_parts(mut self) -> Vec<*mut ()>
{
std::mem::replace(&mut self.pointers, Vec::new())
}
/// Consume a vector of pointers and return a new `Store<T>`.
pub fn from_raw_parts(pointers: Vec<*mut ()>) -> Self
{
Self {
pointers,
}
}
/// Free all the pointers in the store without calling their destructors (if the have any).
pub fn free(mut self)
{
for &mut x in self.pointers.iter_mut()
{
unsafe {
alloc::free(x);
}
}
self.pointers.clear()
}
}
impl std::ops::Drop for DynStore
{
fn drop(&mut self)
{
for &mut ptr in self.pointers.iter_mut()
{
unsafe {
drop(ptr::take(ptr));
alloc::free(ptr);
}
}
self.pointers.clear();
}
}
impl<T> IntoIterator for Store<T>
{
type Item = *mut T;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(mut self) -> Self::IntoIter
{
std::mem::replace(&mut self.pointers, Vec::new()).into_iter()
}
}
impl IntoIterator for DynStore
{
type Item = *mut ();
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(mut self) -> Self::IntoIter
{
std::mem::replace(&mut self.pointers, Vec::new()).into_iter()
}
}
use std::iter::FromIterator;
impl<T> FromIterator<*mut T> for Store<T>
{
fn from_iter<I: IntoIterator<Item=*mut T>>(iter: I) -> Self
{
Self {
pointers: Vec::from_iter(iter)
}
}
}
impl<T> FromIterator<*mut T> for DynStore
{
fn from_iter<I: IntoIterator<Item=*mut T>>(iter: I) -> Self
{
Self {
pointers: Vec::from_iter(iter.into_iter().map(|x| x as *mut ()))
}
}
}
Loading…
Cancel
Save