Multitype allocator stub
This commit is contained in:
parent
bdecf3a6cf
commit
8693aae913
@ -12,4 +12,4 @@ bgtu-networks-2-network-abstract = { path = "../abstract" }
|
|||||||
[dependencies.windows]
|
[dependencies.windows]
|
||||||
version = ">=0.41.0, <=0.62.2"
|
version = ">=0.41.0, <=0.62.2"
|
||||||
registry = "crates-io"
|
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"]
|
||||||
@ -2,7 +2,7 @@ use std::ffi::{CStr, CString, c_char};
|
|||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
use std::slice::from_raw_parts_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::Networking::WinSock::WSA_ERROR;
|
||||||
use windows::Win32::System::Diagnostics::Debug::{
|
use windows::Win32::System::Diagnostics::Debug::{
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS,
|
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) -> ! {
|
pub(super) fn throw_from_windows_err_code(code: impl ErrCode) -> ! {
|
||||||
panic!(
|
panic!(
|
||||||
"Windows error [{:X}]: {}",
|
"Windows error [{:X}]: {}",
|
||||||
|
|||||||
@ -1,30 +1,95 @@
|
|||||||
use std::collections::HashMap;
|
use crate::errors::throw_from_windows_err_code;
|
||||||
use std::mem::uninitialized;
|
use std::mem::{offset_of, uninitialized};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::ptr;
|
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> {
|
pub(crate) struct Allocator {
|
||||||
map: HashMap<usize, Pin<Box<T>>>,
|
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 {
|
pub fn new() -> Self {
|
||||||
return Self {
|
unsafe {
|
||||||
map: HashMap::new(),
|
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>>(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,16 +15,16 @@ use windows::Win32::System::IO::OVERLAPPED;
|
|||||||
use windows::Win32::System::Threading::SleepEx;
|
use windows::Win32::System::Threading::SleepEx;
|
||||||
|
|
||||||
pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut Ctx) {
|
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 socket = WindowsOverlappingIcmpSocket::new();
|
||||||
|
|
||||||
let mut recv_task = NonNull::from_mut(&mut heap).as_mut().alloc();
|
let mut recv_task = NonNull::from_mut(&mut heap).as_mut().alloc(|mut p| CallbackData::init_recv(
|
||||||
CallbackData::init_recv(
|
&mut p,
|
||||||
&mut recv_task,
|
|
||||||
NonNull::new_unchecked(ctx),
|
NonNull::new_unchecked(ctx),
|
||||||
NonNull::from_mut(&mut heap),
|
NonNull::from_mut(&mut heap),
|
||||||
);
|
));
|
||||||
|
|
||||||
|
|
||||||
let mut is_receive_enabled = false;
|
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;
|
let mut should_recv_being_enabled = false;
|
||||||
for address in it {
|
for address in it {
|
||||||
let mut task = NonNull::from_mut(&mut heap).as_mut().alloc();
|
let mut task = NonNull::from_mut(&mut heap).as_mut().alloc(|mut p| CallbackData::init_send(
|
||||||
CallbackData::init_send(
|
&mut p,
|
||||||
&mut task,
|
|
||||||
NonNull::new_unchecked(ctx),
|
NonNull::new_unchecked(ctx),
|
||||||
NonNull::from_mut(&mut heap),
|
NonNull::from_mut(&mut heap),
|
||||||
address,
|
address,
|
||||||
);
|
));
|
||||||
|
|
||||||
|
|
||||||
socket.send(&mut task, Some(sending_done::<Ctx>));
|
socket.send(&mut task, Some(sending_done::<Ctx>));
|
||||||
should_recv_being_enabled = true;
|
should_recv_being_enabled = true;
|
||||||
@ -56,7 +56,7 @@ pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut
|
|||||||
|
|
||||||
struct CallbackData<Ctx: ServersContext<WindowsAddressKnown>> {
|
struct CallbackData<Ctx: ServersContext<WindowsAddressKnown>> {
|
||||||
ctx: NonNull<Ctx>,
|
ctx: NonNull<Ctx>,
|
||||||
allocator: NonNull<Allocator<IoTask<Self>>>,
|
allocator: NonNull<Allocator>,
|
||||||
address: WindowsAddressKnown,
|
address: WindowsAddressKnown,
|
||||||
__flags: u32,
|
__flags: u32,
|
||||||
__addrs_size: i32,
|
__addrs_size: i32,
|
||||||
@ -66,7 +66,7 @@ impl<Ctx: ServersContext<WindowsAddressKnown>> CallbackData<Ctx> {
|
|||||||
fn init_send(
|
fn init_send(
|
||||||
task: &mut Pin<&mut IoTask<CallbackData<Ctx>>>,
|
task: &mut Pin<&mut IoTask<CallbackData<Ctx>>>,
|
||||||
ctx: NonNull<Ctx>,
|
ctx: NonNull<Ctx>,
|
||||||
allocator: NonNull<Allocator<IoTask<Self>>>,
|
allocator: NonNull<Allocator>,
|
||||||
address: WindowsAddressKnown,
|
address: WindowsAddressKnown,
|
||||||
) {
|
) {
|
||||||
task.init(Self {
|
task.init(Self {
|
||||||
@ -80,7 +80,7 @@ impl<Ctx: ServersContext<WindowsAddressKnown>> CallbackData<Ctx> {
|
|||||||
fn init_recv(
|
fn init_recv(
|
||||||
task: &mut Pin<&mut IoTask<CallbackData<Ctx>>>,
|
task: &mut Pin<&mut IoTask<CallbackData<Ctx>>>,
|
||||||
ctx: NonNull<Ctx>,
|
ctx: NonNull<Ctx>,
|
||||||
allocator: NonNull<Allocator<IoTask<Self>>>,
|
allocator: NonNull<Allocator>,
|
||||||
) {
|
) {
|
||||||
task.init(Self {
|
task.init(Self {
|
||||||
ctx,
|
ctx,
|
||||||
|
|||||||
@ -46,3 +46,9 @@ impl<E> IoTask<E> {
|
|||||||
return &mut unsafe { Pin::into_inner_unchecked(NonNull::from_mut(self).read()) }.sys;
|
return &mut unsafe { Pin::into_inner_unchecked(NonNull::from_mut(self).read()) }.sys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <E> Drop for IoTask<E> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user