无依赖Rust异步block_on极简实现:如何移除unsafe关键字?
如何在无依赖前提下移除阻塞执行器中的unsafe关键字?
我实现了一个尽可能精简的阻塞执行器,但代码里用到了unsafe关键字,没办法移除。以下是仅用于调试、无外部依赖的代码:
use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; // 创建空操作waker fn dummy_raw_waker() -> RawWaker { fn no_op_clone(_: *const ()) -> RawWaker { dummy_raw_waker() } fn no_op(_: *const ()) {} RawWaker::new( core::ptr::null(), &RawWakerVTable::new(no_op_clone, no_op, no_op, no_op), ) } // 仅用于调试、无依赖的阻塞函数 pub fn debug_only_unsafe_block_on<F: Future>(mut future: F) -> F::Output { let waker = unsafe { Waker::from_raw(dummy_raw_waker()) }; let mut context = Context::from_waker(&waker); // 在栈上Pin future let mut future = unsafe { Pin::new_unchecked(&mut future) }; loop { match future.as_mut().poll(&mut context) { Poll::Ready(val) => return val, Poll::Pending => { // 在真实系统中可能需要切换到其他任务,但本场景仅持续轮询 } } } }
可以在不引入额外依赖的前提下完全移除unsafe关键字,只需对两处核心代码做修改:
替换手动实现的空Waker
Rust标准库从1.51版本起提供了Waker::noop()方法,直接返回一个空操作的waker,完全替代你手动实现的dummy_raw_waker和unsafe { Waker::from_raw(...) }调用,无需任何unsafe。安全Pin Future
原代码用Pin::new_unchecked在栈上Pin非Unpin的Future是不安全的,我们可以将Future放到堆上,通过Box::pin()安全创建Pin<Box<F>>——堆分配的Future被Pin后内存地址固定,不会被移动,完全满足Pin的安全要求。
修改后的完整代码:
use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll, Waker}; // 仅用于调试、无依赖的阻塞函数 pub fn debug_only_block_on<F: Future>(future: F) -> F::Output { let waker = Waker::noop(); let mut context = Context::from_waker(&waker); // 将Future放到堆上并安全Pin let mut future = Box::pin(future); loop { match future.as_mut().poll(&mut context) { Poll::Ready(val) => return val, Poll::Pending => { // 调试场景下持续轮询,无其他任务调度 } } } }
说明
Waker::noop()的行为和你手动实现的空waker完全一致:所有waker操作都是空实现,不会触发任何唤醒逻辑。Box::pin()是标准库提供的安全API,无需手动保证Pin的安全条件,适配所有Future类型。- 这段代码完全移除了unsafe,仅依赖core库,和原代码的调试场景完全匹配。
内容的提问来源于stack exchange,提问作者Poperton
相关产品推荐
相关产品推荐

