基于结构体内部Sleep实现DelayedValue的Future trait遇Pin错误求助
解决封装Tokio Sleep Future时的Pin编译错误
我想要实现一个DelayedValue Future,让它在指定时长后返回目标值,于是打算封装Tokio crate里的Sleep Future,但遇到了Pin相关的编译错误,始终没法调用底层Sleep成员的poll方法。以下是体现需求但无法编译的代码:
use futures::task::{Context, Poll}; use futures::Future; use std::pin::Pin; use tokio::time::{sleep, Sleep, Duration}; struct DelayedValue<T> { value: T, sleep: Sleep, } impl<T> Future for DelayedValue<T> { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { match &mut self.sleep.poll(cx) { Poll::Ready(()) => Poll::Ready(self.value), x => x, } } } #[tokio::main] async fn main() { let dv = DelayedValue { value: 10_u8, sleep: sleep(Duration::from_millis(5000)), }; println!("waiting for delayed value"); let v = dv.await; println!("delayed value: {}", v); }
错误原因
Sleep的poll方法要求调用者是Pin<&mut Sleep>,但直接通过self.sleep只能拿到&mut Sleep,没有被固定(Pin),不符合方法的参数要求。- 当
Sleep完成后,直接访问self.value会因为self是Pin<&mut Self>而无法直接获取所有权,违反Pin的安全规则。
修复后的代码
use futures::task::{Context, Poll}; use futures::Future; use std::pin::Pin; use tokio::time::{sleep, Sleep, Duration}; struct DelayedValue<T> { value: T, sleep: Sleep, } impl<T> Future for DelayedValue<T> { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { // 用map_mut获取Pin住的Sleep引用 match self.map_mut(|s| &mut s.sleep).poll(cx) { Poll::Ready(()) => { // 当Sleep完成,取出内部的value Poll::Ready(Pin::into_inner(self).value) } Poll::Pending => Poll::Pending, } } } #[tokio::main] async fn main() { let dv = DelayedValue { value: 10_u8, sleep: sleep(Duration::from_millis(1000)), }; println!("waiting for delayed value"); let v = dv.await; println!("delayed value: {}", v); }
关键修改说明
- 使用
Pin::map_mut方法,将Pin<&mut DelayedValue<T>>转换为Pin<&mut Sleep>,满足Sleep::poll的参数要求。 - 当
Sleep完成后,调用Pin::into_inner将Pin<&mut Self>还原为&mut Self,此时可以安全取出value,因为Future已经完成,不会再被轮询(poll),不存在移动Pin值的风险。
运行这段代码后,程序会等待1秒,然后输出delayed value: 10,符合预期功能。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

