Multitype allocator stub

This commit is contained in:
Andrew Golovashevich 2026-03-03 22:23:38 +03:00
parent bdecf3a6cf
commit 8693aae913
5 changed files with 109 additions and 32 deletions

View File

@ -12,4 +12,4 @@ bgtu-networks-2-network-abstract = { path = "../abstract" }
[dependencies.windows]
version = ">=0.41.0, <=0.62.2"
registry = "crates-io"
features = ["Win32_System_IO", "Win32_Networking", "Win32_Networking_WinSock", "Win32_System_Diagnostics", "Win32_System_Diagnostics_Debug", "Win32_System_Threading"]
features = ["Win32_System_IO", "Win32_Networking", "Win32_Networking_WinSock", "Win32_System_Diagnostics", "Win32_System_Diagnostics_Debug", "Win32_System_Threading", "Win32_System_Memory"]

View File

@ -2,7 +2,7 @@ use std::ffi::{CStr, CString, c_char};
use std::ptr;
use std::ptr::null_mut;
use std::slice::from_raw_parts_mut;
use windows::Win32::Foundation::{HLOCAL, LocalFree};
use windows::Win32::Foundation::{HLOCAL, LocalFree, WIN32_ERROR};
use windows::Win32::Networking::WinSock::WSA_ERROR;
use windows::Win32::System::Diagnostics::Debug::{
FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS,
@ -39,6 +39,12 @@ impl ErrCode for HRESULT {
}
}
impl ErrCode for WIN32_ERROR {
fn to_dword(&self) -> u32 {
return self.0
}
}
pub(super) fn throw_from_windows_err_code(code: impl ErrCode) -> ! {
panic!(
"Windows error [{:X}]: {}",

View File

@ -1,30 +1,95 @@
use std::collections::HashMap;
use std::mem::uninitialized;
use crate::errors::throw_from_windows_err_code;
use std::mem::{offset_of, uninitialized};
use std::pin::Pin;
use std::ptr;
use std::ptr::{NonNull, null_mut};
use windows::Win32::Foundation::{GetLastError, HANDLE};
use windows::Win32::System::Memory::{HEAP_FLAGS, HEAP_NO_SERIALIZE, HeapAlloc, HeapCreate};
pub(crate) struct Allocator<T> {
map: HashMap<usize, Pin<Box<T>>>,
pub(crate) struct Allocator {
win_heap: HANDLE,
last: Option<NonNull<dyn Cell>>,
}
impl<T> Allocator<T> {
trait Cell {
fn get_prev(&self) -> Option<NonNull<dyn Cell>>;
fn set_prev(&mut self, p: Option<NonNull<dyn Cell>>);
fn get_next(&self) -> Option<NonNull<dyn Cell>>;
fn set_next(&mut self, p: Option<NonNull<dyn Cell>>);
}
struct CellImpl<T> {
prev: Option<NonNull<dyn Cell>>,
next: Option<NonNull<dyn Cell>>,
value: T,
}
impl<T> Cell for CellImpl<T> {
fn get_prev(&self) -> Option<NonNull<dyn Cell>> {
return self.prev;
}
fn set_prev(&mut self, p: Option<NonNull<dyn Cell>>) {
self.prev = p;
}
fn get_next(&self) -> Option<NonNull<dyn Cell>> {
return self.next;
}
fn set_next(&mut self, p: Option<NonNull<dyn Cell>>) {
self.next = p;
}
}
impl Allocator {
pub fn new() -> Self {
return Self {
map: HashMap::new(),
unsafe {
let h;
match HeapCreate(HEAP_NO_SERIALIZE, 0, 0) {
Ok(hh) => h = hh,
Err(err) => throw_from_windows_err_code(err.code()),
}
return Allocator {
win_heap: h,
last: None,
};
}
pub unsafe fn alloc<'s>(&'s mut self) -> Pin<&'s mut T> {
let ptr = Box::pin(uninitialized::<T>());
let addr = ptr::from_ref(ptr.as_ref().get_ref()).addr();
self.map.insert(addr, ptr);
return self
.map
.get_mut(&addr)
.unwrap_or_else(|| unreachable!())
.as_mut();
}
pub unsafe fn free(&mut self, p: Pin<&mut T>) {
pub unsafe fn alloc<'s, T: Drop + 'static>(
&'s mut self,
init: impl FnOnce(Pin<&mut T>),
) -> Pin<&'s mut T> {
let mut p = NonNull::new(
HeapAlloc(
self.win_heap,
HEAP_FLAGS::default(),
size_of::<CellImpl<T>>(),
)
.cast::<CellImpl<T>>(),
)
.unwrap_or_else(|| throw_from_windows_err_code(GetLastError()));
if let Some(mut last) = self.last {
last.as_mut().set_next(Some(p));
}
p.as_mut().prev = self.last;
p.as_mut().next = None;
self.last = Some(p);
init(Pin::new_unchecked(&mut p.as_mut().value));
return Pin::new_unchecked(&mut p.as_mut().value);
}
pub unsafe fn free<T: Drop>(&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<T>, value))
.cast::<CellImpl<T>>(),
);
}
}

View File

@ -15,16 +15,16 @@ use windows::Win32::System::IO::OVERLAPPED;
use windows::Win32::System::Threading::SleepEx;
pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut Ctx) {
let mut heap = Allocator::<IoTask<CallbackData<_>>>::new();
let mut heap = Allocator::new();
let mut socket = WindowsOverlappingIcmpSocket::new();
let mut recv_task = NonNull::from_mut(&mut heap).as_mut().alloc();
CallbackData::init_recv(
&mut recv_task,
let mut recv_task = NonNull::from_mut(&mut heap).as_mut().alloc(|mut p| CallbackData::init_recv(
&mut p,
NonNull::new_unchecked(ctx),
NonNull::from_mut(&mut heap),
);
));
let mut is_receive_enabled = false;
@ -33,13 +33,13 @@ pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut
let mut should_recv_being_enabled = false;
for address in it {
let mut task = NonNull::from_mut(&mut heap).as_mut().alloc();
CallbackData::init_send(
&mut task,
let mut task = NonNull::from_mut(&mut heap).as_mut().alloc(|mut p| CallbackData::init_send(
&mut p,
NonNull::new_unchecked(ctx),
NonNull::from_mut(&mut heap),
address,
);
));
socket.send(&mut task, Some(sending_done::<Ctx>));
should_recv_being_enabled = true;
@ -56,7 +56,7 @@ pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut
struct CallbackData<Ctx: ServersContext<WindowsAddressKnown>> {
ctx: NonNull<Ctx>,
allocator: NonNull<Allocator<IoTask<Self>>>,
allocator: NonNull<Allocator>,
address: WindowsAddressKnown,
__flags: u32,
__addrs_size: i32,
@ -66,7 +66,7 @@ impl<Ctx: ServersContext<WindowsAddressKnown>> CallbackData<Ctx> {
fn init_send(
task: &mut Pin<&mut IoTask<CallbackData<Ctx>>>,
ctx: NonNull<Ctx>,
allocator: NonNull<Allocator<IoTask<Self>>>,
allocator: NonNull<Allocator>,
address: WindowsAddressKnown,
) {
task.init(Self {
@ -80,7 +80,7 @@ impl<Ctx: ServersContext<WindowsAddressKnown>> CallbackData<Ctx> {
fn init_recv(
task: &mut Pin<&mut IoTask<CallbackData<Ctx>>>,
ctx: NonNull<Ctx>,
allocator: NonNull<Allocator<IoTask<Self>>>,
allocator: NonNull<Allocator>,
) {
task.init(Self {
ctx,

View File

@ -46,3 +46,9 @@ impl<E> IoTask<E> {
return &mut unsafe { Pin::into_inner_unchecked(NonNull::from_mut(self).read()) }.sys;
}
}
impl <E> Drop for IoTask<E> {
fn drop(&mut self) {
todo!()
}
}