簡體   English   中英

使用Rust期貨運行異步可變操作

[英]Running asynchronous mutable operations with Rust futures

我正在使用tokio-rs在Rust中構建一個服務,並且對這個技術堆棧感到滿意。 我現在正試圖將包含寫入的異步操作和借用檢查器的困難時間聯系起來。

我簡化的最小代碼示例如下:

extern crate futures; // 0.1.21

use futures::Future;
use std::{cell::RefCell, rc::Rc};

trait RequestProcessor {
    fn prepare(&self) -> Box<Future<Item = (), Error = ()>>;
    fn process(&mut self, request: String) -> Box<Future<Item = (), Error = ()>>;
}

struct Service {
    processor: Rc<RefCell<RequestProcessor>>,
}

impl Service {
    fn serve(&mut self, request: String) -> Box<Future<Item = (), Error = ()>> {
        let processor_clone = self.processor.clone();
        let result_fut = self
            .processor
            .borrow()
            .prepare()
            .and_then(move |_| processor_clone.borrow_mut().process(request));
        Box::new(result_fut)
    }
}

fn main() {}

作為一個簡短的總結,在異步准備步驟之后,我正在嘗試運行另一個寫self字段的異步操作。 沒有可變性,這對於普通的Rc成員很容易,但是可變性會破壞它,產生以下錯誤:

error[E0597]: `processor_clone` does not live long enough
  --> src/main.rs:22:32
   |
22 |             .and_then(move |_| processor_clone.borrow_mut().process(request));
   |                                ^^^^^^^^^^^^^^^                             - `processor_clone` dropped here while still borrowed
   |                                |
   |                                borrowed value does not live long enough
   |
   = note: values in a scope are dropped in the opposite order they are created

我希望這應該有用,我不知道哪些可變參考仍然借用。 我認為process()應該在返回未來之后釋放處理器的&mut self ,因此不應該發生編譯錯誤。

你能解釋一下根本原因嗎? 如何將此示例更改為編譯器接受?

有時,如果將值拆分為多行,則更容易看到生命周期錯誤。 讓我們嘗試使用有問題的閉包:

.and_then(move |_| {
    let c = processor_clone;
    let mut d = c.borrow_mut();
    let e = d.process(request);
    e
});

如果你編譯它...它的工作原理。 如果我們嘗試重新組合這些行,我們可能會失敗:

.and_then(move |_| {
    let c = processor_clone;
    c.borrow_mut().process(request)
});

這個工作:

.and_then(move |_| {
    let c = processor_clone;
    return c.borrow_mut().process(request);
});

唯一的區別是顯式返回和分號。 這非常類似於在返回使用StdinLock的結果時,為什么借用stdin保留? 所以讓我們試試其中一個答案的建議,以啟用非詞匯生命 這允許您的原始代碼也可以編譯。

TL; DR:這是Rust目前的借用檢查程序實現中的一個弱點,並且在某些時候會被神奇地修復。 與此同時,我建議將其寫成兩行:

.and_then(move |_| {
    let mut c = processor_clone.borrow_mut();
    c.process(request)
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM