Arc 内元素的 Rust 生命周期<Vec<>>

问题描述 投票:0回答:1

我有 Golang 背景,正在开发一个 Rust 项目,该项目具有以下设置:

我有一个基于 2 个通道的标准生产者/消费者设置:“工作通道”和“结果通道”。
生产者线程将工作发送到工作通道并从结果通道接收结果。
消费者线程从工作通道接收工作并将结果发送到结果通道。

我在 Rust Playground 中创建了一个最小可重现的问题示例(粘贴在下面)。 [注意:我知道这是解决这个特定问题的愚蠢方法;在现实世界的问题中,我有一个向量作为输入,我使用一些元素作为哈希图的键,该哈希图返回包含元素的计算结果]

我遇到的问题是我想在输出向量中引用输入向量内的元素。
在 MRE 中,我有一个

Vec<User>
作为输入,并有一个经过过滤的
Vec<User>
作为输出。理想情况下,我希望有一个
Vec<&User>
作为输出,只需引用输入元素,这样我就不必克隆它们
underage.push(el.clone());
)。

我相信我明白导致此问题的原因,但我能想到的唯一解决方案是将

Arc<Vec<Arc<User>>
作为输入传递,这看起来很糟糕。

有没有办法返回

Arc<Vec<&User>>
将向量内元素引用的生命周期与向量的生命周期连接起来?

谢谢!

use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;

#[derive(Debug, Clone)]
struct User {
    age: u32,
}

fn main() {
    let my_vec: Vec<User> = vec!(
        User{age: 10},
        User{age: 20},
        User{age: 15},
        User{age: 18},
    );
    let arc_my_vec = Arc::new(my_vec);
    
    // this is a thread that listens for work on a rx_work channel
    // and puts the result of the work on a tx_result channel
    let (tx_work, rx_work) = channel();
    let (tx_result, rx_result) = channel();
    let t = thread::spawn(move || {
        loop {
            let users: Arc<Vec<User>> = rx_work.recv().unwrap();
            
            let mut underage = vec![];
            for el in users.iter() {
                if el.age < 18 {
                    underage.push(el.clone());
                }
            }
            tx_result.send(underage).unwrap();
        }
    });
    
    let this_vec = Arc::clone(&arc_my_vec);
    // put work on the channel that's followed by the thread
    tx_work.send(this_vec).unwrap();

    // receive the result from the thread work
    let underage = rx_result.recv().unwrap();
    dbg!(underage);

    t.join().unwrap();
}
rust
1个回答
0
投票

尝试一下这里

use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;

#[derive(Debug)]
struct User {
    age: u32,
}

fn main() {
    let my_vec: Vec<User> = vec![
        User { age: 10 },
        User { age: 20 },
        User { age: 15 },
        User { age: 18 },
    ];
    let arc_my_vec = Arc::new(my_vec);

    // Specify the type of messages for the work channel
    let (tx_work, rx_work): (std::sync::mpsc::Sender<Vec<usize>>, std::sync::mpsc::Receiver<Vec<usize>>) = channel();
    let (tx_result, rx_result) = channel();

    let arc_my_vec_clone = Arc::clone(&arc_my_vec);
    let t = thread::spawn(move || {
        while let Ok(indices) = rx_work.recv() {
            let underage_indices: Vec<usize> = indices
                .into_iter()
                .filter(|&i| arc_my_vec_clone[i].age < 18)
                .collect();

            tx_result.send(underage_indices).unwrap();
        }
    });

    // Send the indices of the vector to the worker thread
    let indices: Vec<usize> = (0..arc_my_vec.len()).collect();
    tx_work.send(indices).unwrap();

    // Receive the result from the worker thread
    let underage_indices = rx_result.recv().unwrap();
    let underage_users: Vec<&User> = underage_indices
        .iter()
        .map(|&i| &arc_my_vec[i])
        .collect();

    dbg!(underage_users);

    t.join().unwrap();
}

© www.soinside.com 2019 - 2024. All rights reserved.