initial commit
This commit is contained in:
commit
d581440210
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
.idea
|
16
Cargo.lock
generated
Normal file
16
Cargo.lock
generated
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shortpointer"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "shortpointer"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
lazy_static = "1"
|
144
src/main.rs
Normal file
144
src/main.rs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
use core::alloc::Layout;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::mem::size_of;
|
||||||
|
use core::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
use std::fmt::Formatter;
|
||||||
|
use std::mem::size_of_val;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
#[repr(C, align(65536))]
|
||||||
|
struct Pool {
|
||||||
|
data: [u8; 65536],
|
||||||
|
begin: usize,
|
||||||
|
end: usize,
|
||||||
|
last_position: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref POOL: Mutex<Pool> = Mutex::new(Pool { data: [0; 65536], begin: 0, end: 0, last_position: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// halfassed bump allocator just to prove a point.
|
||||||
|
impl Pool {
|
||||||
|
fn alloc(&mut self, layout: Layout) -> u16 {
|
||||||
|
let size = layout.size();
|
||||||
|
let align = layout.align();
|
||||||
|
|
||||||
|
let mut position = self.end + size_of::<u16>(); // space for skip marker
|
||||||
|
let alignmask = align - 1;
|
||||||
|
if position & alignmask != 0 {
|
||||||
|
position += ((position ^ alignmask) & alignmask) + 1;
|
||||||
|
}
|
||||||
|
let new_end = position + size;
|
||||||
|
assert!(new_end < self.data.len(), "ShortPointer memory pool exhausted");
|
||||||
|
// using most significant bit as whether it's been freed
|
||||||
|
assert!(position - self.last_position < 32768, "Alignment caused 32KiB limit overrun");
|
||||||
|
|
||||||
|
let skip_marker = 0x8000_u16.to_ne_bytes();
|
||||||
|
self.data[position - 2..position].copy_from_slice(&skip_marker);
|
||||||
|
self.end = new_end;
|
||||||
|
if self.begin == 0 {
|
||||||
|
self.begin = position;
|
||||||
|
}
|
||||||
|
self.last_position = position;
|
||||||
|
position as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dealloc(&mut self, sptr: u16) {
|
||||||
|
let mut position = sptr as usize;
|
||||||
|
unsafe {
|
||||||
|
let skip_marker_ptr = self.data.as_mut_ptr().add(position - 2) as *mut u16;
|
||||||
|
*skip_marker_ptr &= 0x7fff;
|
||||||
|
// see how much we can free
|
||||||
|
let mut skip_marker = *skip_marker_ptr;
|
||||||
|
let update_begin = self.begin == position;
|
||||||
|
while skip_marker & 0x8000 == 0 {
|
||||||
|
if skip_marker == 0 {
|
||||||
|
// last object, we can reclaim memory back to sptr
|
||||||
|
self.end = sptr as usize;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
position += skip_marker as usize;
|
||||||
|
}
|
||||||
|
skip_marker = *(self.data.as_ptr().add(position - 2) as *const u16);
|
||||||
|
}
|
||||||
|
if update_begin {
|
||||||
|
self.begin = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.begin == self.end {
|
||||||
|
// all objects freed, we can reset the entire state
|
||||||
|
self.begin = 0;
|
||||||
|
self.end = 0;
|
||||||
|
self.last_position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Pool {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f, "Pool {{ data: [_; 65536], begin: {}, end: {}, last_position: {} }}",
|
||||||
|
self.begin,
|
||||||
|
self.end,
|
||||||
|
self.last_position,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ShortPointer<T>(u16, PhantomData<T>);
|
||||||
|
|
||||||
|
impl<T> Drop for ShortPointer<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
POOL.lock().unwrap().dealloc(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ShortPointer<T> {
|
||||||
|
fn deref_inner(&self) -> &mut T {
|
||||||
|
unsafe {
|
||||||
|
((((POOL.lock().unwrap().data.as_mut_ptr()) as usize) + (self.0 as usize)) as *mut T).as_mut().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(obj: T) -> Self {
|
||||||
|
let layout = Layout::for_value(&obj);
|
||||||
|
let mut sptr = Self(POOL.lock().unwrap().alloc(layout), PhantomData::default());
|
||||||
|
let uninitialized = core::mem::replace(sptr.deref_mut(), obj);
|
||||||
|
core::mem::forget(uninitialized);
|
||||||
|
sptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for ShortPointer<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.deref_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DerefMut for ShortPointer<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
self.deref_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_must_use)] // dbg! statements
|
||||||
|
fn main() {
|
||||||
|
dbg!(POOL.lock().unwrap());
|
||||||
|
{
|
||||||
|
let foo = ShortPointer::new([1, 2, 3, 4, 5]);
|
||||||
|
dbg!(POOL.lock().unwrap());
|
||||||
|
{
|
||||||
|
let bar = ShortPointer::new(0x900dCafeDa7e5_u64);
|
||||||
|
dbg!(POOL.lock().unwrap());
|
||||||
|
println!("{} | {:?} | {:x}", size_of_val(&foo), *foo, *bar);
|
||||||
|
}
|
||||||
|
dbg!(POOL.lock().unwrap());
|
||||||
|
}
|
||||||
|
dbg!(POOL.lock().unwrap());
|
||||||
|
}
|
Loading…
Reference in a new issue