Somebase tests for allocator
This commit is contained in:
parent
6691847830
commit
744ecde879
135
network/windows/src/eventloop/_allocator_tests.rs
Normal file
135
network/windows/src/eventloop/_allocator_tests.rs
Normal file
@ -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);
|
||||||
|
}*/
|
||||||
@ -1,7 +1,10 @@
|
|||||||
use crate::errors::throw_from_windows_err_code;
|
use crate::errors::throw_from_windows_err_code;
|
||||||
|
use std::cell::UnsafeCell;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::thread::panicking;
|
use std::thread::panicking;
|
||||||
use windows::Win32::Foundation::{GetLastError, HANDLE};
|
use windows::Win32::Foundation::{GetLastError, HANDLE};
|
||||||
use windows::Win32::System::Memory::{
|
use windows::Win32::System::Memory::{
|
||||||
@ -10,7 +13,8 @@ use windows::Win32::System::Memory::{
|
|||||||
|
|
||||||
pub(crate) struct Allocator {
|
pub(crate) struct Allocator {
|
||||||
win_heap: HANDLE,
|
win_heap: HANDLE,
|
||||||
last: Option<NonNull<Header>>,
|
last: UnsafeCell<Option<NonNull<Header>>>,
|
||||||
|
__not_send: PhantomData<Rc<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
@ -30,7 +34,8 @@ impl Allocator {
|
|||||||
}
|
}
|
||||||
return Allocator {
|
return Allocator {
|
||||||
win_heap: h,
|
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>(
|
pub unsafe fn alloc<'s, T>(&'s self, init: impl FnOnce(&mut Pin<&mut T>)) -> Pin<&'s mut T> {
|
||||||
&'s mut self,
|
|
||||||
init: impl FnOnce(&mut Pin<&mut T>),
|
|
||||||
) -> Pin<&'s mut T> {
|
|
||||||
let mut h = NonNull::new(
|
let mut h = NonNull::new(
|
||||||
HeapAlloc(
|
HeapAlloc(
|
||||||
self.win_heap,
|
self.win_heap,
|
||||||
@ -67,13 +69,13 @@ impl Allocator {
|
|||||||
let mut p = Pin::new_unchecked(h.as_mut().value.cast::<T>().as_mut());
|
let mut p = Pin::new_unchecked(h.as_mut().value.cast::<T>().as_mut());
|
||||||
heap_free_on_exit::<false, _>(self.win_heap, h.cast(), || init(&mut p));
|
heap_free_on_exit::<false, _>(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);
|
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().next = None;
|
||||||
h.as_mut().destructor = Self::_destructor::<T>;
|
h.as_mut().destructor = Self::_destructor::<T>;
|
||||||
self.last = Some(h);
|
self.last.get().write(Some(h));
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -82,7 +84,7 @@ impl Allocator {
|
|||||||
drop(obj.cast::<T>().read())
|
drop(obj.cast::<T>().read())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn free<T: Drop>(&mut self, p: Pin<&mut T>) {
|
pub unsafe fn free<T: Drop>(&self, p: Pin<&mut T>) {
|
||||||
let p = NonNull::from_mut(Pin::into_inner_unchecked(p));
|
let p = NonNull::from_mut(Pin::into_inner_unchecked(p));
|
||||||
let h = NonNull::new_unchecked(
|
let h = NonNull::new_unchecked(
|
||||||
p.as_ptr()
|
p.as_ptr()
|
||||||
@ -93,8 +95,8 @@ impl Allocator {
|
|||||||
|
|
||||||
h.next.map(|mut n| n.as_mut().prev = h.prev);
|
h.next.map(|mut n| n.as_mut().prev = h.prev);
|
||||||
h.prev.map(|mut n| n.as_mut().next = h.next);
|
h.prev.map(|mut n| n.as_mut().next = h.next);
|
||||||
if self.last == Some(NonNull::from_mut(h)) {
|
if self.last.get().read() == Some(NonNull::from_mut(h)) {
|
||||||
self.last = h.prev;
|
self.last.get().write(h.prev);
|
||||||
}
|
}
|
||||||
heap_free_on_exit::<true, _>(self.win_heap, NonNull::from_mut(h).cast(), || {
|
heap_free_on_exit::<true, _>(self.win_heap, NonNull::from_mut(h).cast(), || {
|
||||||
(h.destructor)(p.cast::<c_void>())
|
(h.destructor)(p.cast::<c_void>())
|
||||||
@ -140,7 +142,7 @@ impl Drop for Allocator {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
drop(RecursiveHeapDestructor {
|
drop(RecursiveHeapDestructor {
|
||||||
win_heap: self.win_heap,
|
win_heap: self.win_heap,
|
||||||
next: self.last,
|
next: unsafe { self.last.get().read() },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
mod socket;
|
mod socket;
|
||||||
mod task;
|
mod task;
|
||||||
mod allocator;
|
mod allocator;
|
||||||
|
mod _allocator_tests;
|
||||||
|
|
||||||
use socket::WindowsOverlappingIcmpSocket;
|
use socket::WindowsOverlappingIcmpSocket;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user