在HashMap中维护对结构的可变引用

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

是否可以借用一个可更改的HashMap内容的引用,并在不妨碍只读访问的情况下长时间使用它?

这是为了保持一个窗口来了解系统中不同组件的状态,这些组件是独立运行的(通过Tokio),需要被监控。

举个例子。

use std::sync::Arc;
use std::collections::HashMap;

struct Container {
    running : bool,
    count : u8
}

impl Container {
    fn run(&mut self) {
        for i in 1..100 {
            self.count = i;
        }

        self.running = false;
    }
}

fn main() {
    let mut map = HashMap::new();

    let mut container = Arc::new(
        Box::new(
            Container {
                running: true,
                count: 0
            }
        )
    );

    map.insert(0, container.clone());

    container.run();

    map.remove(&0);
}

这适用于一个Tokio驱动的程序,其中多个操作将异步进行,并且需要对它们的整体状态进行监控。

这个问题 可以借用一个临时的可变引用,但这不能作为 run() 函数需要时间来完成。

rust automatic-ref-counting
1个回答
0
投票

基于Jmb和Stargateur的建议,重做了这个,以使用一个 RwLock 内部。这些内部可以通过拥有操纵它们的方法来重新设计,但基本的东西在这里。

use std::sync::Arc;
use std::sync::RwLock;
use std::collections::HashMap;

#[derive(Debug)]
struct ContainerState {
    running : bool,
    count : u8
}

struct Container {
    state : Arc<RwLock<ContainerState>>
}

impl Container {
    fn run(&self) {
        for i in 1..100 {
            let mut state = self.state.write().unwrap();
            state.count = i;
        }

        {
            let mut state = self.state.write().unwrap();

            state.running = false;
        }
    }
}

fn main() {
    let mut map = HashMap::new();

    let state = Arc::new(
        RwLock::new(
            ContainerState {
                running: true,
                count: 0
            }
        )
    );

    map.insert(0, state);

    let container = Container {
        state: map[&0].clone()
    };

    container.run();

    println!("Final state: {:?}", map[&0]);

    map.remove(&0);
}

我所遗漏的最关键的东西是 你可以有一个可改变的引用。 多个不可更改的引用,而且它们是相互排斥的。我最初的理解是,这两个限制是独立的。

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