Rust 如何将特殊的NotReady逻辑添加到tokio io?
我正在尝试创建一个Rust 如何将特殊的NotReady逻辑添加到tokio io?,rust,future,rust-tokio,Rust,Future,Rust Tokio,我正在尝试创建一个流,它将等待特定字符进入缓冲区。我知道在BufRead上有read_until(),但实际上我需要一个自定义解决方案,因为这是实现等待缓冲区中某个特定字符串(或者,例如,发生regexp匹配)的垫脚石 在我第一次遇到这个问题的项目中,问题是当我从内部future获取一个Ready(41;并从函数返回NotReady时,未来处理就挂起了。我发现我不应该那样做(最后一段)。然而,我没有得到的是,那一段中承诺的实际替代方案是什么。我阅读了东京网站上所有已发表的文件,目前对我来说没有任
流
,它将等待特定字符进入缓冲区。我知道在BufRead
上有read_until()
,但实际上我需要一个自定义解决方案,因为这是实现等待缓冲区中某个特定字符串(或者,例如,发生regexp匹配)的垫脚石
在我第一次遇到这个问题的项目中,问题是当我从内部future获取一个Ready(41;
并从函数返回NotReady
时,未来处理就挂起了。我发现我不应该那样做(最后一段)。然而,我没有得到的是,那一段中承诺的实际替代方案是什么。我阅读了东京网站上所有已发表的文件,目前对我来说没有任何意义
下面是我当前的代码。不幸的是,我不能使它更简单和更小,因为它已经坏了。目前的结果是:
Err(Custom { kind: Other, error: Error(Shutdown) })
Err(Custom { kind: Other, error: Error(Shutdown) })
Err(Custom { kind: Other, error: Error(Shutdown) })
<ad infinum>
.如果需要更多数据,您需要再次调用
poll\u read
,直到找到您要查找的内容或poll\u read
返回NotReady
您可能希望避免在一个任务中循环太长时间,因此如果poll\u read
没有返回NotReady
,您可以构建一个yield\u task
函数来调用;它确保在运行其他挂起的任务后尽快再次调用您的任务
要使用它,只需运行returnyield_task()代码>
fn屈服内部(){
使用期货::任务;
任务::当前().notify();
}
#[在线(始终)]
pub fn yield_task()->Poll{
屈服内部();
Ok(异步::NotReady)
}
另见
随着新的async/await API的推出,futures::task::current
消失了;相反,您需要一个引用,它作为新trait方法的参数提供
如果您已经手动实现该特性,只需插入:
context.waker().wake_by_ref();
return std::task::Poll::Pending;
或者自己构建一个实现类型,只产生一次:
pub struct Yield {
ready: bool,
}
impl core::future::Future for Yield {
type Output = ();
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
let this = self.get_mut();
if this.ready {
core::task::Poll::Ready(())
} else {
cx.waker().wake_by_ref();
this.ready = true; // ready next round
core::task::Poll::Pending
}
}
}
pub fn yield_task() -> Yield {
Yield { ready: false }
}
pub struct Yield {
ready: bool,
}
impl core::future::Future for Yield {
type Output = ();
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
let this = self.get_mut();
if this.ready {
core::task::Poll::Ready(())
} else {
cx.waker().wake_by_ref();
this.ready = true; // ready next round
core::task::Poll::Pending
}
}
}
pub fn yield_task() -> Yield {
Yield { ready: false }
}
yield_task().await;