Improve Drop guards

This commit is contained in:
Nadja Reitzenstein 2022-06-23 13:02:40 +02:00
parent 18d69063fd
commit 9a86bae45a

View File

@ -24,6 +24,7 @@ pub(crate) struct RawProc<'a, F, R, S> {
pub(crate) pdata: *const ProcData, pub(crate) pdata: *const ProcData,
pub(crate) schedule: *const S, pub(crate) schedule: *const S,
pub(crate) future: *mut F, pub(crate) future: *mut F,
// TODO: Replace with `MaybeUninit`
pub(crate) output: *mut R, pub(crate) output: *mut R,
// Make the lifetime 'a of the future invariant // Make the lifetime 'a of the future invariant
@ -135,7 +136,6 @@ where
/// Wakes a waker. /// Wakes a waker.
unsafe fn wake(ptr: *const ()) { unsafe fn wake(ptr: *const ()) {
let raw = Self::from_ptr(ptr); let raw = Self::from_ptr(ptr);
let _guard = (&(*raw.pdata).span).enter();
let id = (&(*raw.pdata).span) let id = (&(*raw.pdata).span)
.id() .id()
.map(|id| id.into_u64()) .map(|id| id.into_u64())
@ -208,7 +208,6 @@ where
/// Wakes a waker by reference. /// Wakes a waker by reference.
unsafe fn wake_by_ref(ptr: *const ()) { unsafe fn wake_by_ref(ptr: *const ()) {
let raw = Self::from_ptr(ptr); let raw = Self::from_ptr(ptr);
let _guard = (&(*raw.pdata).span).enter();
let id = (&(*raw.pdata).span) let id = (&(*raw.pdata).span)
.id() .id()
.map(|id| id.into_u64()) .map(|id| id.into_u64())
@ -277,7 +276,6 @@ where
/// Clones a waker. /// Clones a waker.
unsafe fn clone_waker(ptr: *const ()) -> RawWaker { unsafe fn clone_waker(ptr: *const ()) -> RawWaker {
let raw = Self::from_ptr(ptr); let raw = Self::from_ptr(ptr);
let _guard = (&(*raw.pdata).span).enter();
let id = (&(*raw.pdata).span) let id = (&(*raw.pdata).span)
.id() .id()
.map(|id| id.into_u64()) .map(|id| id.into_u64())
@ -309,7 +307,6 @@ where
#[inline] #[inline]
unsafe fn decrement(ptr: *const ()) { unsafe fn decrement(ptr: *const ()) {
let raw = Self::from_ptr(ptr); let raw = Self::from_ptr(ptr);
let _guard = (&(*raw.pdata).span).enter();
let id = (&(*raw.pdata).span) let id = (&(*raw.pdata).span)
.id() .id()
.map(|id| id.into_u64()) .map(|id| id.into_u64())
@ -383,9 +380,11 @@ where
/// Ticking will call `poll` once and re-schedule the task if it returns `Poll::Pending`. If /// Ticking will call `poll` once and re-schedule the task if it returns `Poll::Pending`. If
/// polling its future panics, the proc will be closed and the panic propagated into the caller. /// polling its future panics, the proc will be closed and the panic propagated into the caller.
unsafe fn tick(ptr: *const ()) { unsafe fn tick(ptr: *const ()) {
let raw = Self::from_ptr(ptr); let mut raw = Self::from_ptr(ptr);
// Enter the span associated with the process to track execution time if enabled.
let _guard = (&(*raw.pdata).span).enter();
// Create a context from the raw proc pointer and the vtable inside the its pdata. // Create a context from the raw proc pointer and the vtable inside its pdata.
let waker = ManuallyDrop::new(Waker::from_raw(RawWaker::new( let waker = ManuallyDrop::new(Waker::from_raw(RawWaker::new(
ptr, ptr,
&(*raw.pdata).vtable.raw_waker, &(*raw.pdata).vtable.raw_waker,
@ -431,9 +430,9 @@ where
// Poll the inner future, but surround it with a guard that closes the proc in case polling // Poll the inner future, but surround it with a guard that closes the proc in case polling
// panics. // panics.
let guard = Guard(raw); let drop_guard = Guard(&mut raw);
let poll = <F as Future>::poll(Pin::new_unchecked(&mut *raw.future), cx); let poll = <F as Future>::poll(drop_guard.pin_future(), cx);
mem::forget(guard); drop_guard.disable();
match poll { match poll {
Poll::Ready(out) => { Poll::Ready(out) => {
@ -548,21 +547,43 @@ impl<'a, F, R, S> Clone for RawProc<'a, F, R, S> {
} }
impl<'a, F, R, S> Copy for RawProc<'a, F, R, S> {} impl<'a, F, R, S> Copy for RawProc<'a, F, R, S> {}
#[repr(transparent)]
/// A guard that closes the proc if polling its future panics. /// A guard that closes the proc if polling its future panics.
struct Guard<'a, F, R, S>(RawProc<'a, F, R, S>) struct Guard<'guard, 'a, F, R, S>(&'guard mut RawProc<'a, F, R, S>)
where where
F: Future<Output = R> + 'a, F: Future<Output = R> + 'a,
R: 'a, R: 'a,
S: Fn(LightProc) + 'a; S: Fn(LightProc) + 'a;
impl<'a, F, R, S> Drop for Guard<'a, F, R, S> impl<'guard, 'a, F, R, S> Guard<'guard, 'a, F, R, S>
where
F: Future<Output = R> + 'a,
R: 'a,
S: Fn(LightProc) + 'a,
{
#[inline(always)]
/// Disable the guard again.
///
/// This does essentially nothing but prevents the Drop implementation from being called
fn disable(self) {
// Put `self` in a ManuallyDrop telling the compiler to explicitly not call Drop::drop
let _ = ManuallyDrop::new(self);
}
#[inline(always)]
unsafe fn pin_future(&self) -> Pin<&mut F> {
Pin::new_unchecked(&mut *self.0.future)
}
}
impl<'a, F, R, S> Drop for Guard<'_, 'a, F, R, S>
where where
F: Future<Output = R> + 'a, F: Future<Output = R> + 'a,
R: 'a, R: 'a,
S: Fn(LightProc) + 'a, S: Fn(LightProc) + 'a,
{ {
fn drop(&mut self) { fn drop(&mut self) {
let raw = self.0; let raw = &self.0;
let ptr = raw.pdata as *const (); let ptr = raw.pdata as *const ();
unsafe { unsafe {