I'm writing a virtual machine and currently working on its memory which is implemented using a linked list. I have implemented malloc which adds a new node to the list, free which marks a node to be reused by malloc and now I am working on realloc. The problem i have is that I cannot copy data between two nodes of the linked list due to there being two mutable references, here is a minimum example:
use std::collections::LinkedList;
struct MemoryBlock {
address: u64,
size: u64,
data: Vec<u8>
}
struct Memory {
blocks: LinkedList<MemoryBlock>,
}
impl Memory {
fn malloc(&mut self, alloc_size: u64) -> u64 {
self.blocks.push_back(MemoryBlock {
address: 1,
size: alloc_size,
data: vec![0x00]
});
1
}
fn realloc(&mut self, address: u64, new_size: u64) -> u64 {
let new_address = self.malloc(new_size);
let mut old_block = self.blocks.iter_mut().find(|b| b.address == address).unwrap();
let mut new_block = self.blocks.iter_mut().find(|b| b.address == new_address).unwrap();
new_block.data[0] = old_block.data[0];
new_address
}
}
fn main() {
let mut memory = Memory {
blocks: LinkedList::new()
};
memory.blocks.push_back(MemoryBlock {
address: 0,
size: 1,
data: vec![0x00]
});
memory.realloc(0, 2);
}
I have tried to make 'old_block' immutable but then I cannot have one mutable and one immutable borrow at the same time. Is there any way to structure my code differently or any other method (other than unsafe) to get it to work? I know I can use a vector and then use slices as a 'hack' to get it done but I would prefer to use a linked list if possible.
new_blockto theold_blockwithout copying, hence the compiler is complaining, as you are still holding references to the same linked list. You need to use.clone()to properly copy the value before taking a second reference (and esnure MemoryBlock derives Clone) or usedrain_filterto remove the block before reassigning it (probably not what you want). Something likelet old_block = self.blocks.iter().find(|b| b.address == address).unwrap().clone();should do the trick, assuming#[derive(Clone)]onMemoryBlock