So now I try to implement one improvement by myself. I follow one of the suggestions made in the bottom of his page.I try to implement double buffering. Now I got a problem mutable references.
You can copy height and width beforehand, then use the copies. That way you won't get overlapping regions of exclusive borrows. (right now readBuf and writeBuf extend the region which self is borrowed exclusively, and you aren't allowed to reuse self in that region. So copying beforehand gets around this by not reusing self in that region)
Please don't post images of code, it makes it harder for me to help you. Please use code fences (as described here to format your code)
Thanks yato, that gets me a little further and I learned something new, of how order matters
However I did not post the entire function, this only postpones the problem.
fn get_buf_mut(&mut self) -> (& Vec<Cell>, &mut Vec<Cell>) {
match &self.active_buf {
One => (& self.cells_buf_two, &mut self.cells_buf_one),
Two => (& self.cells_buf_one, &mut self.cells_buf_two)
}
}
pub fn tick(&mut self) {
let _timer = Timer::new("Universe::tick");
let height = self.height;
let width = self.width;
let (readBuf,writeBuf) = self.get_buf_mut();
{
let _timer = Timer::new("new generation");
for row in 0..height {
for col in 0..width {
let idx = self.get_index(row, col);
let cell = readBuf[idx];
let live_neighbors = self.live_neighbor_count(row, col);
let next_cell = match (cell, live_neighbors) {
(Cell::Alive, x) if x < 2 => Cell::Dead,
(Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive,
(Cell::Alive, x) => Cell::Dead,
(Cell::Dead, 3) => Cell::Alive,
(otherwise,_) => otherwise,
};
writeBuf[idx] = next_cell;
}
}
}
self.switch_active_buffer();
}
fn switch_active_buffer(&mut self) {
self.active_buf = match &self.active_buf {
One => BufActive::Two,
Two => BufActive::One
}
}
fn get_index(&self, row: u32, column: u32) -> usize {
(row * self.width + column) as usize
}
fn live_neighbor_count(&self, row: u32, column: u32) -> u8 {
// ...
}
}
No I get another error:
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src\lib.rs:278:31
|
272 | let (readBuf,writeBuf) = self.get_buf_mut();
| ---- mutable borrow occurs here
...
278 | let idx = self.get_index(row, col);
| ^^^^ immutable borrow occurs here
279 | let cell = readBuf[idx];
| ------- mutable borrow later used here
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src\lib.rs:280:42
|
272 | let (readBuf,writeBuf) = self.get_buf_mut();
| ---- mutable borrow occurs here
...
279 | let cell = readBuf[idx];
| ------- mutable borrow later used here
280 | let live_neighbors = self.live_neighbor_count(row, col);
| ^^^^ immutable borrow occurs here
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src\lib.rs:328:23
|
325 | let (readBuf,writebuf) = self.get_buf_mut();
| ---- mutable borrow occurs here
...
328 | let idx = self.get_index(row, col);
| ^^^^ immutable borrow occurs here
329 | writebuf[idx] = Cell::Alive;
| -------- mutable borrow later used here
error: aborting due to 3 previous errors
I was hoping I could get around that whole issue by putting the double buffer in its own struct. But I was wrong. The problem still exists. This is how I changed the code now:
pub struct DoubleBuffer {
cells_buf_one: Vec<Cell>,
cells_buf_two: Vec<Cell>,
active_buf: BufActive
}
#[wasm_bindgen]
pub struct Universe {
width: u32,
height: u32,
buffer: DoubleBuffer
}
impl DoubleBuffer {
pub fn new(cells: Vec<Cell>) -> Self {
DoubleBuffer {
cells_buf_one : Clone::clone(&cells),
cells_buf_two : cells,
active_buf : BufActive::One
}
}
pub fn switch_active_buffer(&mut self) {
self.active_buf = match &self.active_buf {
One => BufActive::Two,
Two => BufActive::One
}
}
pub fn get_write_buf_mut(&mut self) -> & mut Vec<Cell> {
match &self.active_buf {
One => &mut self.cells_buf_one,
Two => &mut self.cells_buf_two
}
}
pub fn get_read_buf(& self) -> & Vec<Cell> {
match &self.active_buf {
One => & self.cells_buf_one,
Two => & self.cells_buf_two
}
}
pub fn get_buf_mut(&mut self) -> (& Vec<Cell>, &mut Vec<Cell>) {
match &self.active_buf {
One => (& self.cells_buf_two, &mut self.cells_buf_one),
Two => (& self.cells_buf_one, &mut self.cells_buf_two)
}
}
pub fn init(&mut self, cells: Vec<Cell>) {
self.cells_buf_one = Clone::clone(&cells);
self.cells_buf_two = cells;
}
}
impl Universe {
// ...
pub fn tick(&mut self) {
let _timer = Timer::new("Universe::tick");
let height = self.height;
let width = self.width;
let (readBuf,writeBuf) = self.buffer.get_buf_mut();
{
let _timer = Timer::new("new generation");
for row in 0..height {
for col in 0..width {
let idx = self.get_index(row, col);
let cell = readBuf[idx];
let live_neighbors = self.live_neighbor_count(row, col);
let next_cell = match (cell, live_neighbors) {
(Cell::Alive, x) if x < 2 => Cell::Dead,
(Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive,
(Cell::Alive, x) => Cell::Dead,
(Cell::Dead, 3) => Cell::Alive,
(otherwise,_) => otherwise,
};
writeBuf[idx] = next_cell;
}
}
}
self.buffer.switch_active_buffer();
}
}
// ...
}
Still same issue
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src\lib.rs:307:31
|
301 | let (readBuf,writeBuf) = self.buffer.get_buf_mut();
| ----------- mutable borrow occurs here
...
307 | let idx = self.get_index(row, col);
| ^^^^ immutable borrow occurs here
308 | let cell = readBuf[idx];
| ------- mutable borrow later used here
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src\lib.rs:309:42
|
301 | let (readBuf,writeBuf) = self.buffer.get_buf_mut();
| ----------- mutable borrow occurs here
...
308 | let cell = readBuf[idx];
| ------- mutable borrow later used here
309 | let live_neighbors = self.live_neighbor_count(row, col);
| ^^^^ immutable borrow occurs here
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src\lib.rs:350:23
|
347 | let writebuf = self.buffer.get_write_buf_mut();
| ----------- mutable borrow occurs here
...
350 | let idx = self.get_index(row, col);
| ^^^^ immutable borrow occurs here
351 | writebuf[idx] = Cell::Alive;
| -------- mutable borrow later used here