"BorrowMutError" 使用内部可变性模式

"BorrowMutError" using the Interior Mutability Pattern

我正在尝试使用内部可变性模式来共享可变引用。

但是,当我尝试使用与其共享的结构中的引用时,程序出现错误并出现混乱:

thread 'main' panicked at 'already borrowed: BorrowMutError'

代码如下:

use std::rc::Rc;
use std::cell::RefCell;

fn main() {
    let game = Game::init();
    game.start();
}

struct Game {
    ecs: Rc<RefCell<Ecs>>,
}

impl Game {
    pub fn init() -> Game {
        let ecs = Rc::new(RefCell::new(Ecs::new()));
        ecs.borrow_mut().register_systems(vec![
            Box::new(Renderer {
                ecs: Rc::clone(&ecs),
            }),
        ]);
        Game {
            ecs: Rc::clone(&ecs),
        }
    }

    pub fn start(&self) {
        self.ecs.borrow_mut().update();
    }
}

struct Ecs {
    systems: Vec<Box<dyn System>>,
}

impl Ecs {
    fn new() -> Ecs {
        Ecs {
            systems: vec![],
        }
    }

    fn register_systems(&mut self, systems: Vec<Box<dyn System>>) {
        self.systems = systems;
    }

    fn update(&self) {
        for system in self.systems.iter() {
            system.update();
        }
    }

    fn test(&self) {
        println!("done!");
    }
}

trait System {
    fn update(&self);
}


struct Renderer {
    ecs: Rc<RefCell<Ecs>>,
}

impl System for Renderer {
    fn update(&self) {
        self.ecs.borrow_mut().test();
    }
}

问题似乎在以下行:

self.ecs.borrow_mut().test();

这里有什么问题?跟性格有关系吗?还是我需要以其他方式调用函数 test

确实,Renderer 中的 ecs 成员是 ecs 成员的克隆 在 Game,即他们 都拥有 相同的 Ecs

当您 borrow_mut() ecs 成员 Game 然后迭代 的元素,你到达 Renderer 其中 borrow_mut()s 相同 Ecs。 这在运行时被检测到然后恐慌,这是预期的 RefCell.

的行为

如果您在这两种情况下都将 borrow_mut() 更改为 borrow(), 这不再恐慌,因为多次不可变借用 是允许的。

我不知道这段代码的确切用途,但我不确定 从 Renderer 中整体借用 Ecs 是个好主意。 我假设 interior-mutability 应该适用于每个 单独存储组件而不是整个 Ecs.