diff --git a/network/windows/src/eventloop/allocator.rs b/network/windows/src/eventloop/allocator.rs index 3a4dc53..2b4d9f8 100644 --- a/network/windows/src/eventloop/allocator.rs +++ b/network/windows/src/eventloop/allocator.rs @@ -1,45 +1,21 @@ use crate::errors::throw_from_windows_err_code; -use std::mem::{offset_of, uninitialized}; +use std::ffi::c_void; use std::pin::Pin; -use std::ptr; -use std::ptr::{NonNull, null_mut}; +use std::ptr::NonNull; use windows::Win32::Foundation::{GetLastError, HANDLE}; -use windows::Win32::System::Memory::{HEAP_FLAGS, HEAP_NO_SERIALIZE, HeapAlloc, HeapCreate}; +use windows::Win32::System::Memory::{ + HeapAlloc, HeapCreate, HeapFree, HEAP_FLAGS, HEAP_NO_SERIALIZE, +}; pub(crate) struct Allocator { win_heap: HANDLE, - last: Option>, + last: Option>, } -trait Cell { - fn get_prev(&self) -> Option>; - fn set_prev(&mut self, p: Option>); - fn get_next(&self) -> Option>; - fn set_next(&mut self, p: Option>); -} - -struct CellImpl { - prev: Option>, - next: Option>, - value: T, -} - -impl Cell for CellImpl { - fn get_prev(&self) -> Option> { - return self.prev; - } - - fn set_prev(&mut self, p: Option>) { - self.prev = p; - } - - fn get_next(&self) -> Option> { - return self.next; - } - - fn set_next(&mut self, p: Option>) { - self.next = p; - } +struct Header { + prev: Option>, + next: Option>, + destructor: unsafe fn(NonNull), } impl Allocator { @@ -57,39 +33,78 @@ impl Allocator { } } - pub unsafe fn alloc<'s, T: Drop + 'static>( + const fn _calc_offset() -> usize { + match size_of::
() % align_of::() == 0 { + true => return size_of::
(), + false => { + return size_of::
() + + (align_of::() - size_of::
() % align_of::()); + } + } + } + + pub unsafe fn alloc<'s, T>( &'s mut self, - init: impl FnOnce(Pin<&mut T>), + init: impl FnOnce(&mut Pin<&mut T>), ) -> Pin<&'s mut T> { - let mut p = NonNull::new( + let mut h = NonNull::new( HeapAlloc( self.win_heap, HEAP_FLAGS::default(), - size_of::>(), + Self::_calc_offset::() + size_of::(), ) - .cast::>(), + .cast::
(), ) .unwrap_or_else(|| throw_from_windows_err_code(GetLastError())); if let Some(mut last) = self.last { - last.as_mut().set_next(Some(p)); + last.as_mut().next = Some(h); } - p.as_mut().prev = self.last; - p.as_mut().next = None; - self.last = Some(p); + h.as_mut().prev = self.last; + h.as_mut().next = None; + h.as_mut().destructor = Self::_destructor::; + self.last = Some(h); - init(Pin::new_unchecked(&mut p.as_mut().value)); + let mut p = Pin::new_unchecked( + &mut *(h + .as_ptr() + .map_addr(|a| a + Self::_calc_offset::()) + .cast::()), + ); - return Pin::new_unchecked(&mut p.as_mut().value); + init(&mut p); + + return p; + } + + unsafe fn _destructor(obj: NonNull) { + drop(obj.cast::().read()) } pub unsafe fn free(&mut self, p: Pin<&mut T>) { - let p = Pin::into_inner_unchecked(p); - let c = NonNull::new_unchecked( - NonNull::new_unchecked(p) - .as_ptr() - .map_addr(|a| a - offset_of!(CellImpl, value)) - .cast::>(), - ); + let p = NonNull::from_mut(Pin::into_inner_unchecked(p)); + let h = NonNull::new_unchecked( + p.as_ptr() + .map_addr(|a| a - Self::_calc_offset::()) + .cast::
(), + ) + .as_mut(); + + h.next.map(|mut n| n.as_mut().prev = h.prev); + h.prev.map(|mut n| n.as_mut().next = h.next); + if self.last == Some(NonNull::from_mut(h)) { + self.last = h.prev; + } + + (h.destructor)(p.cast::()); + + match HeapFree( + self.win_heap, + HEAP_FLAGS::default(), + Some((h as *mut Header).cast()), + ) { + Ok(_) => return, + Err(err) => throw_from_windows_err_code(err.code()) + }; } }