rust 当T没有实现Copy时,如何返回Arc&lt;Mutex &gt;后面的值< T>?

j9per5c4  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(137)

我一直在尝试用以下函数初始化一个值(这里是hashbrown的hashmap):

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;

#[derive(Clone)]
struct Entity;

fn create_value(center: (f32, f32), length: f32) -> HashMap<(i32, i32), Option<Entity>> {
    let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
    let mut handles = vec![];

    for i in 0..5 {
        for j in 0..5 {
            let city_thread = Arc::clone(&cities);
            handles.push(thread::spawn(move || {
                // do stuff in parallel
                if let Ok(mut cities) = city_thread.lock() {
                    cities.insert((i, j), None);
                } 
            }));
        }
    }

    for handle in handles {
        handle.join().unwrap();
    }

    // this part is the problem
    if let Ok(city) = cities.lock() {
        let city = city.clone();
        return city;
    } else {
        panic!()
    }
}

字符串
我得到以下错误:

error[E0597]: `cities` does not live long enough
  --> src/lib.rs:29:23
   |
9  |     let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
   |         ------ binding `cities` declared here
...
29 |     if let Ok(city) = cities.lock() {
   |                       ^^^^^^-------
   |                       |
   |                       borrowed value does not live long enough
   |                       a temporary with access to the borrow is created here ...
...
35 | }
   | -
   | |
   | `cities` dropped here while still borrowed
   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Result<MutexGuard<'_, HashMap<(i32, i32), Option<Entity>>>, PoisonError<MutexGuard<'_, HashMap<(i32, i32), Option<Entity>>>>>`
   |
   = note: the temporary is part of an expression at the end of a block;
           consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
   |
29 ~     let x = if let Ok(city) = cities.lock() {
30 |         let city = city.clone();
 ...
33 |         panic!()
34 ~     }; x
   |


我知道我做错了什么,但我找不到任何东西或方法来返回值。

nkcskrwz

nkcskrwz1#

在线程结束后,你不再需要ArcMutex,所以我会在最后解开它们,并返回内部的HashMap

for handle in handles {
    handle.join().unwrap();
}

let cities = Arc::into_inner(cities).unwrap();
let cities = Mutex::into_inner(cities).unwrap();
cities

字符串
Playground

wztqucjr

wztqucjr2#

我们需要将city.clone()的结果放在一个变量中,该变量在最后一个if let块之前声明,并将returnif let块中移出。

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;

#[derive(Clone)]
struct Entity;

fn create_value(center: (f32, f32), length: f32) -> HashMap<(i32, i32), Option<Entity>> {
    let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
    let mut handles = vec![];

    for i in 0..5 {
        for j in 0..5 {
            let city_thread = Arc::clone(&cities);
            handles.push(thread::spawn(move || {
                // do stuff in parallel
                if let Ok(mut cities) = city_thread.lock() {
                    cities.insert((i, j), None);
                }
            }));
        }
    }

    for handle in handles {
        handle.join().unwrap();
    }

    let result;
    if let Ok(city) = cities.lock() {
        result = city.clone();
    } else {
        panic!()
    }

    result
}

字符串
或者,我们可以通过在if let后面添加一个通配符来避免它成为“一个位于块末尾的表达式”。这很奇怪,但它有效!

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;

#[derive(Clone)]
struct Entity;

fn create_value(center: (f32, f32), length: f32) -> HashMap<(i32, i32), Option<Entity>> {
    let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
    let mut handles = vec![];

    for i in 0..5 {
        for j in 0..5 {
            let city_thread = Arc::clone(&cities);
            handles.push(thread::spawn(move || {
                // do stuff in parallel
                if let Ok(mut cities) = city_thread.lock() {
                    cities.insert((i, j), None);
                } 
            }));
        }
    }

    for handle in handles {
        handle.join().unwrap();
    }

    // this part is the problem
    if let Ok(city) = cities.lock() {
        let city = city.clone();
        return city;
    } else {
        panic!()
    }
    
    ;
}


(我推荐第一种方法)。

相关问题