如何装箱Arc和Mutexed变量?

时间:2018-12-02 23:51:38

标签: multithreading rust automatic-ref-counting mutex

以下代码在闭包中获取一些变量,并返回包含该数据的结构。

即使我将结构装箱并克隆变量,我也无法返回带有该数据的结构;他们不可能超出这个范围。我曾考虑过使用回调闭包,但是我真的不想这么做。有没有办法在没有回调的情况下将其删除?

pub fn get(addr: &str) -> std::io::Result<Box<Response>> {
    use std::sync::{Arc, Mutex};
    let mut crl = curl::easy::Easy::new();
    crl.url(format!("{}{}", API_ADDR, addr).as_str()).unwrap();

    // extract headers
    let headers: Vec<String> = Vec::with_capacity(10);
    let headers = Arc::new(Mutex::new(headers));
    {
        let headers = headers.clone();
        crl.header_function(move |h| {
            let mut headers = headers.lock().unwrap();
            (*headers).push(String::from_utf8_lossy(h).into_owned());
            true
        })
        .unwrap();
    }

    // extract body
    let body = Arc::new(Mutex::new(String::with_capacity(1024)));
    {
        let body = body.clone();
        crl.write_function(move |b| {
            let mut body = body.lock().unwrap();
            body.push_str(std::str::from_utf8(b).unwrap());
            Ok(b.len())
        })
        .unwrap();
    }
    crl.perform().unwrap();
    Ok(Box::new(Response {
        resp: body.lock().unwrap().clone(),
        headers: headers.lock().unwrap().clone(),
    }))
}

1 个答案:

答案 0 :(得分:1)

关键错误似乎就是这个:

error[E0597]: `body` does not live long enough
  --> src/lib.rs:85:15
   |
85 |         resp: body.lock().unwrap().clone(),
   |               ^^^^ borrowed value does not live long enough
...
89 | }
   | - `body` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

标题对象相同。

通过存根大量代码,我能够简化此过程:

use std::sync::{Arc, Mutex};

pub struct Response {
    resp: String,
    headers: Vec<String>,
}

pub fn get(addr: &str) -> std::io::Result<Box<Response>> {
    let headers: Vec<String> = Vec::with_capacity(10);
    let headers = Arc::new(Mutex::new(headers));
    let body = Arc::new(Mutex::new(String::with_capacity(1024)));
    Ok(Box::new(Response {
        resp: body.lock().unwrap().clone(),
        headers: headers.lock().unwrap().clone(),
    }))
}

我认为这与在最终Ok(Box::new(...))返回值中构造的临时变量的生存期有关。

我可以通过将锁/拉开到外面来进行编译。

let body = body.lock().unwrap();
let headers = headers.lock().unwrap();
Ok(Box::new(Response {
    resp: body.clone(),
    headers: headers.clone(),
}))

Why do I get "does not live long enough" in a return value?中给出的更详细的解释中,我发现您可以将其写为

return Ok(Box::new(Response {
    resp: body.lock().unwrap().clone(),
    headers: headers.lock().unwrap().clone(),
}));

即添加显式return和结尾的分号。虽然我有一种clip不休的感觉,但可能会说它的风格不好。