feat: add downcast on Sleep trait#3125
Conversation
|
I think it'd be a bit cleaner to implement downcasting methods directly on Sleep without requiring implementors to deal with it: mod private {
pub struct PrivacyToken;
}
pub trait Sleep: Send + Sync + Future<Output = ()> {
// PrivacyToken can't be named outside of this crate, so it prevents anyone from overriding this default
// implementation in another crate. That allows us to trust it to be correct in the downcast methods below.
#[doc(hidden)]
fn __private_api_type_id(&self, _: private::PrivacyToken) -> TypeId {
TypeId::of::<Self>()
}
}
impl dyn Sleep {
/// Returns `true` if the sleep's type is `T`.
pub fn is<T>(&self) -> bool
where
T: Sleep,
{
self.__private_api_type_id(private::PrivacyToken) == TypeId::of::<T>()
}
/// Attempts to downcast the sleep to the type `T` if it has that type.
pub fn downcast_ref<T>(&self) -> Option<&T>
where
T: Sleep,
{
if self.is::<T>() {
unsafe { Some(&*(self as *const dyn Sleep as *const T)) }
} else {
None
}
}
// downcast_pin as well similarly
} |
That's a good point. We can probably make Though, |
|
Are there any relevant non-'static Sleep implementations? |
fc9e8f3 to
b7d56c9
Compare
I don't think so, but we shouldn't be too concerned about it now anyways imo. I have also added some docs to it |
seanmonstar
left a comment
There was a problem hiding this comment.
I think this looks goot to me, @sfackler anything else you'd need?
src/rt/mod.rs
Outdated
|
|
||
| pub mod timer; | ||
|
|
||
| pub use timer::*; |
There was a problem hiding this comment.
I'd suggest this be an explicit list, just to prevent any accidents now or in the future.
src/rt/mod.rs
Outdated
| //! If the `runtime` feature is disabled, the types in this module can be used | ||
| //! to plug in other runtimes. | ||
|
|
||
| pub mod timer; |
There was a problem hiding this comment.
Perhaps let's start with the module being private, we can always make it public later if it'd be helpful.
src/rt/timer.rs
Outdated
| /// A future returned by a `Timer`. | ||
| pub trait Sleep: Send + Sync + Future<Output = ()> { | ||
| #[doc(hidden)] | ||
| /// This method is private and should not be implemented by downstream crate |
There was a problem hiding this comment.
can not be implemented, not should not be implemented.
src/rt/timer.rs
Outdated
| //! if sleep.downcast_ref::<TokioSleep>().is_some() { | ||
| //! *sleep = self.sleep_until(new_deadline); | ||
| //! } |
There was a problem hiding this comment.
This doesn't make much sense to me. The whole point of downcasting is to not have to create a new timer.
There was a problem hiding this comment.
Think I understood the issue better now. I updated the example code with an implementation of tokio::time::Sleep::reset
src/rt/timer.rs
Outdated
| /// Downcast the Sleep object to its original type | ||
| pub fn downcast_ref<T>(&self) -> Option<&T> | ||
| where | ||
| T: Sleep + 'static, | ||
| { | ||
| if self.is::<T>() { | ||
| unsafe { Some(&*(self as *const dyn Sleep as *const T)) } | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
|
|
||
| /// Similar to `downcast_ref` but returns a mutable version instead | ||
| pub fn downcast_mut<T>(&mut self) -> Option<&mut T> | ||
| where | ||
| T: Sleep + 'static, | ||
| { | ||
| if self.is::<T>() { | ||
| unsafe { Some(&mut *(self as *mut dyn Sleep as *mut T)) } | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
I don't think these two downcast methods are going to be too useful, since reset is working with a &mut Pin<Box<dyn Sleep>>. I think we'd probably need a pub fn downcast_pin_mut<T>(self: Pin<&mut Self>) -> Option<Pin<&mut T>> probably?
|
I think it'd be good to update the test |
|
Hey @dswij, just wanted to check if you think you'll have time to update this. No worries if you can't, just checking to reduce duplicate work. :) |
Sorry for the delay, I was on a break a while ago and I haven't caught up to my backlog yet. I'll try to take a look at this PR on the weekend 🙂 |
4dc245c to
6858fab
Compare
This commit adds `as_any` downcast method for the `Sleep` trait. BREAKING CHANGE: `Sleep` trait now needs `as_any` implementation
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.
|
@seanmonstar @sfackler sorry for the delay, turned out it took a while for me to get back to this. Would you guys able to help give another round of review? |
|
@seanmonstar sorry to nag, but is there anything I can do to move this forward? |
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. Closes hyperium#3027
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. Closes hyperium#3027 Signed-off-by: Sven Pfennig <s.pfennig@reply.de>
closes #3027
This pr adds a downcast for the
Sleeptrait.