方法一:简单方法
这种方法是将正在变异的位分别传递(例如,如果您的CPU正在变异VM的内存,则只需将其传递给执行):
#[derive(Default, Debug)]
struct CPU;
#[derive(Default, Debug)]
struct Memory { data: Vec<u8> }
#[derive(Default, Debug)]
pub struct VM {
cpu: CPU,
memory: Memory
}
impl CPU {
pub fn execute(&mut self, mem: &mut Memory) -> Result<(), &'static str> {
println!("Executing");
mem.data = b"deadbeaf".to_vec();
Ok(())
}
}
impl VM {
pub fn run(&mut self) {
self.cpu.execute(&mut self.memory);
println!("CPU changed memory to {:#?}", self.memory);
}
}
pub fn main() {
let mut vm = VM::default();
vm.run();
}
优点:
非常简单易懂,易于处理。
缺点:
有些受限制,需要传递一些东西。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=54836ccd4d8dc091846a2bb64df2d4f4
方法二:使用Rc<RefCell>
这种设计也有些天真:
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Default, Debug)]
struct CPU {
ip: u8,
r1: u8,
r2: u8,
}
#[derive(Default, Debug)]
struct Memory { data: Vec<u8> }
#[derive(Default, Debug)]
pub struct VM {
cpu: Rc<RefCell<CPU>>,
memory: Rc<RefCell<Memory>>
}
impl CPU {
pub fn execute(&mut self, vm: &VM) -> Result<(), &'static str> {
println!("Executing");
let mut mem = vm.memory.borrow_mut();
mem.data = b"deadbeaf".to_vec();
self.ip += 1;
Ok(())
}
}
impl VM {
pub fn run(&self) {
let mut cpu = self.cpu.borrow_mut();
cpu.execute(&self).unwrap();
println!("CPU changed memory to {:#?}", self.memory);
}
}
pub fn main() {
let vm = VM::default();
println!("VM: {:#?}", vm);
vm.run();
println!("VM: {:#?}", vm);
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=725587bae3d71159fe94530ac8542e68
在这里,我们可以传递VM,并且资源会根据需要可变地或不可变地借用适当的资源。
评论
请将我所说的视为高度个人化的意见,并谨慎对待(换句话说,不必将我所说的视为“正确”做事方式)。
我认为,您应该考虑如何重新设计代码,使得只有一个“协调器”(状态机),而不是每个组件(例如CPU)都知道其他每个组件。
Edit 1:如下面的评论中所指出的那样,我添加了多余的RefCell
,这是Approach II Redux:
方法二:使用RefCell
use std::cell::RefCell;
#[derive(Default, Debug)]
struct CPU {
ip: u8,
_r1: u8,
_r2: u8,
}
#[derive(Default, Debug)]
struct Memory { data: Vec<u8> }
#[derive(Default, Debug)]
pub struct VM {
cpu: RefCell<CPU>,
memory: RefCell<Memory>
}
impl CPU {
pub fn execute(&mut self, vm: &VM) -> Result<(), &'static str> {
println!("Executing");
let mut mem = vm.memory.borrow_mut();
mem.data = b"deadbeaf".to_vec();
self.ip += 1;
Ok(())
}
}
impl VM {
pub fn run(&self) {
let mut cpu = self.cpu.borrow_mut();
cpu.execute(&self).unwrap();
println!("CPU changed memory to {:#?}", self.memory);
}
}
pub fn main() {
let vm = VM::default();
println!("VM: {:#?}", vm);
vm.run();
println!("VM: {:#?}", vm);
}
VM
,因为它拥有CPU
,而你正在尝试可变地分别借用。相反,尝试将execute
更改为接受Memory
而不是VM
。 - PitaJVM
而不是self
?但最好只传递内存。 - Chayim Friedmanself.a.b(&mut self)
有点可疑。移除VM,并使用单独的对象,例如cpu.execute(&mut memory)
。 - Aitch