繁体   English   中英

无法推断适当的生命周期:向期货借入可变缓冲区

[英]Cannot infer an appropriate lifetime: Borrowing mutable buffers to Futures

我实现了具有以下高级逻辑的Tokio Future

  1. 调用函数recv_dgram 当收到一个小的数据Future ,这应该返回一个准备就绪的Future
  2. Future准备就绪时,保留小数据报。
  3. 如果我们有足够的小数据报来重构大数据报,则将Future设置为就绪并返回重构的数据报。 否则,请返回步骤1。

我有一些我一生都无法理解的问题。 我创建了一个独立的简化代码段来演示它。

在下面的代码中, RecvMsgFuture ,当接收到足够多的小数据RecvMsg就可以使用。 recv_dgram是一个返回Future的函数,当小数据报到达时, Future已准备就绪。

我正在尝试编译以下代码( Playground ):

extern crate futures;
use self::futures::{Future, Poll, Async};

struct RecvMsg<'d,R>
where 
    R: for <'r> FnMut(&'r mut [u8]) -> Box<Future<Item=&'r mut [u8], Error=()> + 'r>,
{
    recv_dgram: R,
    temp_buff: Vec<u8>,
    opt_read_future: Option<Box<Future<Item=&'d mut [u8], Error=()> + 'd>>,
}

impl<'d,R> Future for RecvMsg<'d,R>
where 
    R: for <'r> FnMut(&'r mut [u8]) -> Box<Future<Item=&'r mut [u8], Error=()> + 'r>,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, ()> {

        // Obtain a future datagram, 
        let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
        // Code compiles if this line is commented out:
        self.opt_read_future = Some(fdgram);
        return Ok(Async::NotReady);
    }
}

fn main() {}

这是我收到的错误消息:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src/main.rs:25:44
   |
25 |         let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
   |                                            ^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:5...
  --> src/main.rs:22:5
   |
22 | /     fn poll(&mut self) -> Poll<Self::Item, ()> {
23 | |
24 | |         // Obtain a future datagram, 
25 | |         let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
...  |
28 | |         return Ok(Async::NotReady);
29 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:25:44
   |
25 |         let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
   |                                            ^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'd as defined on the impl at 13:1...
  --> src/main.rs:13:1
   |
13 | / impl<'d,R> Future for RecvMsg<'d,R>
14 | | where 
15 | |     R: for <'r> FnMut(&'r mut [u8]) -> Box<Future<Item=&'r mut [u8], Error=()> + 'r>,
16 | | {
...  |
29 | |     }
30 | | }
   | |_^
note: ...so that expression is assignable (expected std::option::Option<std::boxed::Box<futures::Future<Error=(), Item=&'d mut [u8]> + 'd>>, found std::option::Option<std::boxed::Box<futures::Future<Error=(), Item=&mut [u8]>>>)
  --> src/main.rs:27:32
   |
27 |         self.opt_read_future = Some(fdgram);
   |                                ^^^^^^^^^^^^

我对可能出什么问题有一些想法。 我知道如果我注释掉:

reading_state.opt_read_future = Some(fdgram);

代码编译成功。 另外,我怀疑在这里将reading_state.temp_buff用作参数:

let mut fdgram = (reading_state.frag_msg_receiver.recv_dgram)(
                &mut reading_state.temp_buff);

与问题有关。 (另请参见为什么我不能在同一结构中存储值和对该值的引用?

实现Future但不具有'static生存期”的类型几乎没有用,因为事件循环将无法运行。

我也认为Future::Item生命周期很糟糕; 我看不到类型系统如何在将来真正完成释放寿命的情况下帮助您确定控制流程。

因此,您可能需要使用R: FnMut(Vec<u8>) -> Box<Future<Item=Vec<u8>, Error=()>>代替recv_dgram函数。 它将接收一个缓冲区,该缓冲区应该将新接收到的数据附加到该缓冲区(它可以使用reserve()和“不安全”缓冲区填充+ set_len()进行优化)。 您也可以将Vec包装为某些自定义类型,以强制实施“仅追加”语义。

现在您应该意识到可变性不会对这个功能有多大帮助-您可以连续调用10次而无需等待返回的期货完成。 相反,您可能想传递明确的状态。 还可以避免装箱,并接受任何可通过IntoFuture转换的结果:

// `S` is the state, `F` something convertible to a future `F::Future`.
pub struct RecvMsg<R, F, S>
where
    F: IntoFuture<Item=(S, Vec<u8>), Error=()>,
    R: FnMut(S, Vec<u8>) -> F,
{
    recv_dgram: R,
    opt_read_future: Option<F::Future>,
}

现在,当前暂挂的读操作变为Option<F::Future> ,并且缓冲区位于该暂挂操作中。

每当对包装程序进行轮询时,都将需要轮询此挂起的读取操作(并且尚未完全完成)!

总而言之,它看起来像这样:

操场

extern crate futures;
use self::futures::{IntoFuture,Future, Poll, Async};

pub struct RecvMsg<R, F, S>
where
    F: IntoFuture<Item=(S, Vec<u8>), Error=()>,
    R: FnMut(S, Vec<u8>) -> F,
{
    recv_dgram: R,
    pending: Option<F::Future>,
}

impl<R, F, S> RecvMsg <R, F, S>
where
    F: IntoFuture<Item=(S, Vec<u8>), Error=()>,
    R: FnMut(S, Vec<u8>) -> F,
{
    pub fn new(mut recv_dgram: R, initial_state: S) -> Self {
        let start = recv_dgram(initial_state, Vec::new()).into_future();
        RecvMsg{
            recv_dgram: recv_dgram,
            pending: Some(start)
        }
    }
}

impl<R, F, S> Future for RecvMsg <R, F, S>
where
    F: IntoFuture<Item=(S, Vec<u8>), Error=()>,
    R: FnMut(S, Vec<u8>) -> F,
{
    type Item = Vec<u8>;
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.pending.take() {
            Some(mut p) => {
                match p.poll()? {
                    Async::Ready((state, buf)) => {
                        if buf.len() > 1024 {
                            // enough data
                            Ok(Async::Ready(buf))
                        } else {
                            // not enough data, read more
                            let next = (self.recv_dgram)(state, buf).into_future();
                            self.pending = Some(next);
                            Ok(Async::NotReady)
                        }
                    },
                    Async::NotReady => {
                        // still waiting for more data
                        self.pending = Some(p);
                        Ok(Async::NotReady)
                    },
                }
            },
            None => Ok(Async::NotReady), // already completed
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM