Skip to content

Commit e84f2a2

Browse files
committed
async drop tests for box
1 parent b23df61 commit e84f2a2

File tree

4 files changed

+255
-0
lines changed

4 files changed

+255
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//@ run-pass
2+
//@ check-run-results
3+
// struct `Foo` has both sync and async drop.
4+
// It's used as the allocator of a `Box` which is conditionally moved out of.
5+
// Sync version is called in sync context, async version is called in async function.
6+
7+
#![feature(async_drop, allocator_api)]
8+
#![allow(incomplete_features)]
9+
10+
use std::mem::ManuallyDrop;
11+
12+
//@ edition: 2021
13+
14+
#[inline(never)]
15+
fn myprintln(msg: &str, my_resource_handle: usize) {
16+
println!("{} : {}", msg, my_resource_handle);
17+
}
18+
19+
use std::{
20+
future::{Future, async_drop_in_place, AsyncDrop},
21+
pin::{pin, Pin},
22+
sync::{mpsc, Arc},
23+
task::{Context, Poll, Wake, Waker},
24+
alloc::{AllocError, Allocator, Global, Layout},
25+
ptr::NonNull,
26+
};
27+
28+
struct Foo {
29+
my_resource_handle: usize,
30+
}
31+
32+
impl Foo {
33+
fn new(my_resource_handle: usize) -> Self {
34+
let out = Foo {
35+
my_resource_handle,
36+
};
37+
myprintln("Foo::new()", my_resource_handle);
38+
out
39+
}
40+
}
41+
42+
impl Drop for Foo {
43+
fn drop(&mut self) {
44+
myprintln("Foo::drop()", self.my_resource_handle);
45+
}
46+
}
47+
48+
impl AsyncDrop for Foo {
49+
async fn drop(self: Pin<&mut Self>) {
50+
myprintln("Foo::async drop()", self.my_resource_handle);
51+
}
52+
}
53+
54+
unsafe impl Allocator for Foo {
55+
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
56+
Global.allocate(layout)
57+
}
58+
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
59+
Global.deallocate(ptr, layout);
60+
}
61+
}
62+
63+
struct HasDrop;
64+
impl Drop for HasDrop {
65+
fn drop(&mut self) {}
66+
}
67+
68+
fn main() {
69+
{
70+
let b = Box::new_in(HasDrop, Foo::new(7));
71+
72+
if true {
73+
let _x = *b;
74+
} else {
75+
let _y = b;
76+
}
77+
}
78+
println!("Middle");
79+
block_on(bar(10));
80+
println!("Done")
81+
}
82+
83+
async fn bar(ident_base: usize) {
84+
let b = Box::new_in(HasDrop, Foo::new(ident_base));
85+
86+
if true {
87+
let _x = *b;
88+
} else {
89+
let _y = b;
90+
}
91+
}
92+
93+
fn block_on<F>(fut_unpin: F) -> F::Output
94+
where
95+
F: Future,
96+
{
97+
let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
98+
let mut fut: Pin<&mut F> = unsafe {
99+
Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
100+
};
101+
let (waker, rx) = simple_waker();
102+
let mut context = Context::from_waker(&waker);
103+
let rv = loop {
104+
match fut.as_mut().poll(&mut context) {
105+
Poll::Ready(out) => break out,
106+
// expect wake in polls
107+
Poll::Pending => rx.try_recv().unwrap(),
108+
}
109+
};
110+
let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
111+
let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
112+
loop {
113+
match drop_fut.as_mut().poll(&mut context) {
114+
Poll::Ready(()) => break,
115+
Poll::Pending => rx.try_recv().unwrap(),
116+
}
117+
}
118+
rv
119+
}
120+
121+
fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
122+
struct SimpleWaker {
123+
tx: std::sync::mpsc::Sender<()>,
124+
}
125+
126+
impl Wake for SimpleWaker {
127+
fn wake(self: Arc<Self>) {
128+
self.tx.send(()).unwrap();
129+
}
130+
}
131+
132+
let (tx, rx) = mpsc::channel();
133+
(Waker::from(Arc::new(SimpleWaker { tx })), rx)
134+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Foo::new() : 7
2+
Foo::drop() : 7
3+
Middle
4+
Foo::new() : 10
5+
Foo::async drop() : 10
6+
Done
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//@ run-pass
2+
//@ check-run-results
3+
// struct `Foo` has both sync and async drop.
4+
// `Foo` is always inside `Box`
5+
// Sync version is called in sync context, async version is called in async function.
6+
7+
//@ known-bug: #143658
8+
// async version is never actually called
9+
10+
#![feature(async_drop)]
11+
#![allow(incomplete_features)]
12+
13+
use std::mem::ManuallyDrop;
14+
15+
//@ edition: 2021
16+
17+
#[inline(never)]
18+
fn myprintln(msg: &str, my_resource_handle: usize) {
19+
println!("{} : {}", msg, my_resource_handle);
20+
}
21+
22+
use std::{
23+
future::{Future, async_drop_in_place, AsyncDrop},
24+
pin::{pin, Pin},
25+
sync::{mpsc, Arc},
26+
task::{Context, Poll, Wake, Waker},
27+
};
28+
29+
struct Foo {
30+
my_resource_handle: usize,
31+
}
32+
33+
impl Foo {
34+
fn new(my_resource_handle: usize) -> Self {
35+
let out = Foo {
36+
my_resource_handle,
37+
};
38+
myprintln("Foo::new()", my_resource_handle);
39+
out
40+
}
41+
}
42+
43+
impl Drop for Foo {
44+
fn drop(&mut self) {
45+
myprintln("Foo::drop()", self.my_resource_handle);
46+
}
47+
}
48+
49+
impl AsyncDrop for Foo {
50+
async fn drop(self: Pin<&mut Self>) {
51+
myprintln("Foo::async drop()", self.my_resource_handle);
52+
}
53+
}
54+
55+
fn main() {
56+
{
57+
let _ = Box::new(Foo::new(7));
58+
}
59+
println!("Middle");
60+
block_on(bar(10));
61+
println!("Done")
62+
}
63+
64+
async fn bar(ident_base: usize) {
65+
let _first = Box::new(Foo::new(ident_base));
66+
}
67+
68+
fn block_on<F>(fut_unpin: F) -> F::Output
69+
where
70+
F: Future,
71+
{
72+
let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
73+
let mut fut: Pin<&mut F> = unsafe {
74+
Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
75+
};
76+
let (waker, rx) = simple_waker();
77+
let mut context = Context::from_waker(&waker);
78+
let rv = loop {
79+
match fut.as_mut().poll(&mut context) {
80+
Poll::Ready(out) => break out,
81+
// expect wake in polls
82+
Poll::Pending => rx.try_recv().unwrap(),
83+
}
84+
};
85+
let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
86+
let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
87+
loop {
88+
match drop_fut.as_mut().poll(&mut context) {
89+
Poll::Ready(()) => break,
90+
Poll::Pending => rx.try_recv().unwrap(),
91+
}
92+
}
93+
rv
94+
}
95+
96+
fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
97+
struct SimpleWaker {
98+
tx: std::sync::mpsc::Sender<()>,
99+
}
100+
101+
impl Wake for SimpleWaker {
102+
fn wake(self: Arc<Self>) {
103+
self.tx.send(()).unwrap();
104+
}
105+
}
106+
107+
let (tx, rx) = mpsc::channel();
108+
(Waker::from(Arc::new(SimpleWaker { tx })), rx)
109+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Foo::new() : 7
2+
Foo::drop() : 7
3+
Middle
4+
Foo::new() : 10
5+
Foo::drop() : 10
6+
Done

0 commit comments

Comments
 (0)