From 744ecde879d07065a648a7f21d5d22ce07bbf238 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Wed, 4 Mar 2026 18:18:49 +0300 Subject: [PATCH] Somebase tests for allocator --- .../windows/src/eventloop/_allocator_tests.rs | 135 ++++++++++++++++++ network/windows/src/eventloop/allocator.rs | 28 ++-- network/windows/src/eventloop/mod.rs | 1 + 3 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 network/windows/src/eventloop/_allocator_tests.rs diff --git a/network/windows/src/eventloop/_allocator_tests.rs b/network/windows/src/eventloop/_allocator_tests.rs new file mode 100644 index 0000000..08d3517 --- /dev/null +++ b/network/windows/src/eventloop/_allocator_tests.rs @@ -0,0 +1,135 @@ +#![cfg(test)] + +use super::allocator::Allocator; +use std::panic::catch_unwind; +use std::pin::Pin; +use std::ptr::NonNull; + +#[test] +fn create_destroy() { + let h = Allocator::new(); +} + +struct FlagOnDrop<'a> { + flag: &'a mut bool, +} +impl<'a> FlagOnDrop<'a> { + fn init_pin(self: &mut Pin<&mut Self>, flag: &'a mut bool) { + unsafe { + Pin::into_inner_unchecked(NonNull::from_mut(self).read()).flag = flag; + } + } +} + +impl Drop for FlagOnDrop<'_> { + fn drop(&mut self) { + *self.flag = true; + } +} + +#[test] +fn destruct_auto_1_success() { + let mut destructed = false; + { + let mut h = Allocator::new(); + unsafe { + h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed)); + } + } + assert!(destructed); +} + +#[test] +fn destruct_auto_2_success() { + let mut destructed_1 = false; + let mut destructed_2 = false; + { + let mut h = Allocator::new(); + unsafe { + h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_1)); + h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_2)); + } + } + assert!(destructed_1); + assert!(destructed_2); +} + +#[test] +fn destruct_manual_1_auto_2_success() { + let mut destructed_1 = false; + let mut destructed_2 = false; + { + let mut h = Allocator::new(); + unsafe { + let a = h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_1)); + h.free(a); + h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_2)); + } + } + assert!(destructed_1); + assert!(destructed_2); +} + +#[test] +fn destruct_manual_2_auto_1_success() { + let mut destructed_1 = false; + let mut destructed_2 = false; + { + let mut h = Allocator::new(); + unsafe { + h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_1)); + let b = h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_2)); + h.free(b); + } + } + assert!(destructed_1); + assert!(destructed_2); +} + +#[test] +fn destruct_manual_2_1() { + let mut destructed_1 = false; + let mut destructed_2 = false; + { + let mut h = Allocator::new(); + unsafe { + let a = h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_1)); + let b = h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_2)); + h.free(b); + h.free(a); + } + } + assert!(destructed_1); + assert!(destructed_2); +} + +#[test] +fn destruct_manual_1_2() { + let mut destructed_1 = false; + let mut destructed_2 = false; + { + let mut h = Allocator::new(); + unsafe { + let a = h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_1)); + let b = h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed_2)); + h.free(a); + h.free(b); + } + } + assert!(destructed_1); + assert!(destructed_2); +} +/* +#[allow(unused_must_use)] +#[test] +fn destruct_panic() { + let mut destructed = false; + catch_unwind(|| { + let mut h = Allocator::new(); + unsafe { + h.alloc(|p| FlagOnDrop::init_pin(p, &mut destructed)); + panic!("Test panic"); + } + }); + assert!(destructed); +}*/ diff --git a/network/windows/src/eventloop/allocator.rs b/network/windows/src/eventloop/allocator.rs index ff2131e..7de1894 100644 --- a/network/windows/src/eventloop/allocator.rs +++ b/network/windows/src/eventloop/allocator.rs @@ -1,7 +1,10 @@ use crate::errors::throw_from_windows_err_code; +use std::cell::UnsafeCell; use std::ffi::c_void; +use std::marker::PhantomData; use std::pin::Pin; use std::ptr::NonNull; +use std::rc::Rc; use std::thread::panicking; use windows::Win32::Foundation::{GetLastError, HANDLE}; use windows::Win32::System::Memory::{ @@ -10,7 +13,8 @@ use windows::Win32::System::Memory::{ pub(crate) struct Allocator { win_heap: HANDLE, - last: Option>, + last: UnsafeCell>>, + __not_send: PhantomData>, } struct Header { @@ -30,7 +34,8 @@ impl Allocator { } return Allocator { win_heap: h, - last: None, + last: UnsafeCell::new(None), + __not_send: PhantomData::default(), }; } } @@ -45,10 +50,7 @@ impl Allocator { } } - pub unsafe fn alloc<'s, T>( - &'s mut self, - init: impl FnOnce(&mut Pin<&mut T>), - ) -> Pin<&'s mut T> { + pub unsafe fn alloc<'s, T>(&'s self, init: impl FnOnce(&mut Pin<&mut T>)) -> Pin<&'s mut T> { let mut h = NonNull::new( HeapAlloc( self.win_heap, @@ -67,13 +69,13 @@ impl Allocator { let mut p = Pin::new_unchecked(h.as_mut().value.cast::().as_mut()); heap_free_on_exit::(self.win_heap, h.cast(), || init(&mut p)); - if let Some(mut last) = self.last { + if let Some(mut last) = self.last.get().read() { last.as_mut().next = Some(h); } - h.as_mut().prev = self.last; + h.as_mut().prev = self.last.get().read(); h.as_mut().next = None; h.as_mut().destructor = Self::_destructor::; - self.last = Some(h); + self.last.get().write(Some(h)); return p; } @@ -82,7 +84,7 @@ impl Allocator { drop(obj.cast::().read()) } - pub unsafe fn free(&mut self, p: Pin<&mut T>) { + pub unsafe fn free(&self, p: Pin<&mut T>) { let p = NonNull::from_mut(Pin::into_inner_unchecked(p)); let h = NonNull::new_unchecked( p.as_ptr() @@ -93,8 +95,8 @@ impl Allocator { 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; + if self.last.get().read() == Some(NonNull::from_mut(h)) { + self.last.get().write(h.prev); } heap_free_on_exit::(self.win_heap, NonNull::from_mut(h).cast(), || { (h.destructor)(p.cast::()) @@ -140,7 +142,7 @@ impl Drop for Allocator { fn drop(&mut self) { drop(RecursiveHeapDestructor { win_heap: self.win_heap, - next: self.last, + next: unsafe { self.last.get().read() }, }); } } diff --git a/network/windows/src/eventloop/mod.rs b/network/windows/src/eventloop/mod.rs index 53e3111..1071473 100644 --- a/network/windows/src/eventloop/mod.rs +++ b/network/windows/src/eventloop/mod.rs @@ -1,6 +1,7 @@ mod socket; mod task; mod allocator; +mod _allocator_tests; use socket::WindowsOverlappingIcmpSocket;