Skip to content

Commit 8d0e134

Browse files
committed
feat: allow downcasting pinned Sleep
This commit allows downcasting pinned `Sleep` object to support implementations of `Timer::reset`. One example where this is useful is when using `TokioSleep`, i.e. `Sleep` provided by tokio.
1 parent 50c527f commit 8d0e134

File tree

2 files changed

+24
-22
lines changed

2 files changed

+24
-22
lines changed

benches/support/tokiort.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ impl Timer for TokioTimer {
4343
}
4444

4545
fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
46-
if sleep.downcast_ref::<TokioSleep>().is_some() {
47-
*sleep = self.sleep_until(new_deadline);
46+
if let Some(sleep) = sleep.as_mut().downcast_mut_pin::<TokioSleep>() {
47+
sleep.reset(new_deadline.into())
4848
}
4949
}
5050
}
@@ -81,7 +81,10 @@ impl Future for TokioSleep {
8181
}
8282
}
8383

84-
// Use HasSleep to get tokio::time::Sleep to implement Unpin.
85-
// see https://docs.rs/tokio/latest/tokio/time/struct.Sleep.html
86-
8784
impl Sleep for TokioSleep {}
85+
86+
impl TokioSleep {
87+
pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
88+
self.project().inner.as_mut().reset(deadline.into());
89+
}
90+
}

src/rt/timer.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
//! }
3030
//!
3131
//! fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
32-
//! if sleep.downcast_ref::<TokioSleep>().is_some() {
33-
//! *sleep = self.sleep_until(new_deadline);
32+
//! if let Some(sleep) = sleep.as_mut().downcast_mut_pin::<TokioSleep>() {
33+
//! sleep.reset(new_deadline.into())
3434
//! }
3535
//! }
3636
//! }
@@ -51,6 +51,12 @@
5151
//! }
5252
//!
5353
//! impl Sleep for TokioSleep {}
54+
//!
55+
//! impl TokioSleep {
56+
//! pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
57+
//! self.project().inner.as_mut().reset(deadline.into());
58+
//! }
59+
//! }
5460
//! ````
5561
5662
use std::{
@@ -97,25 +103,18 @@ impl dyn Sleep {
97103
self.__type_id(private::Sealed {}) == TypeId::of::<T>()
98104
}
99105

100-
/// Downcast the Sleep object to its original type
101-
pub fn downcast_ref<T>(&self) -> Option<&T>
102-
where
103-
T: Sleep + 'static,
104-
{
105-
if self.is::<T>() {
106-
unsafe { Some(&*(self as *const dyn Sleep as *const T)) }
107-
} else {
108-
None
109-
}
110-
}
111-
112-
/// Similar to `downcast_ref` but returns a mutable version instead
113-
pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
106+
/// Downcast a pinned &mut Sleep object to its original type
107+
pub fn downcast_mut_pin<T>(self: Pin<&mut Self>) -> Option<Pin<&'static mut T>>
114108
where
115109
T: Sleep + 'static,
116110
{
117111
if self.is::<T>() {
118-
unsafe { Some(&mut *(self as *mut dyn Sleep as *mut T)) }
112+
unsafe {
113+
let inner = Pin::into_inner_unchecked(self);
114+
Some(Pin::new_unchecked(
115+
&mut *(&mut *inner as *mut dyn Sleep as *mut T),
116+
))
117+
}
119118
} else {
120119
None
121120
}

0 commit comments

Comments
 (0)