Skip to content

Commit

Permalink
Fix broken writer react
Browse files Browse the repository at this point in the history
  • Loading branch information
zaclegarssure committed Aug 20, 2023
1 parent 605330d commit dfd4c2c
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 7 deletions.
1 change: 0 additions & 1 deletion src/coroutine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub(crate) enum WaitingReason {

/// A "Fiber" object, througth which a coroutine
/// can interact with the rest of the world.
/// TODO: Clone should be private (otherwise bad things can be done)
pub struct Fib {
// Maybe replace by a real sender receiver channel at some point
pub(crate) yield_sender: Sender<WaitingReason>,
Expand Down
14 changes: 9 additions & 5 deletions src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ impl Executor {
return;
}
}
// To make sure we can detect changes that just happened
{
let world = unsafe { &mut *self.world_window.get().unwrap() };
world.increment_change_tick();
}

let result = self.coroutines.get_mut(&coro).unwrap().as_mut().poll(cx);
let yield_msg = self.yield_msg.receive();
Expand All @@ -238,17 +243,16 @@ impl Executor {
// SAFETY: No other coroutines a running right now, we have exclusive world access
let world = unsafe { &mut *self.world_window.get().unwrap() };
// TODO: Should probably find a better way
for w in accesses.writes().iter().filter(|(e, cid)| {
for write in accesses.writes().iter().filter(|(e, cid)| {
let tick = world
.get_entity(*e)
.unwrap()
.get_change_ticks_by_id(*cid)
.unwrap();
// TODO: Check if it is correct (Looks okay enough)
tick.is_changed(world.last_change_tick(), world.change_tick())
tick.last_changed_tick() == world.change_tick()
}) {
run_cx.write_table.insert(*w, this_node);
if let Some(nexts) = self.waiting_on_change.remove(w) {
run_cx.write_table.insert(*write, this_node);
if let Some(nexts) = self.waiting_on_change.remove(write) {
for c in nexts {
let node = match run_cx.current_node_map.remove(&c) {
Some(n) => {
Expand Down
84 changes: 83 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ mod tests {
for i in 0..5 {
// Note that it works because the coroutine on the the top of the par_or,
// has priority over the one on the bottom, meaning its side effect will be
// seen on the last iteration.
// seen on the last iteration. (Okay I just kind of gave)
executor.tick(w);
assert_eq!(*a.lock().unwrap(), i);
}
Expand Down Expand Up @@ -350,4 +350,86 @@ mod tests {
}
});
}

#[test]
fn not_writing_to_mut_component_has_no_effect() {
let mut world = World::new();
world.insert_resource(Executor::new());
world.insert_resource(Time::new(Instant::now()));
let e = world.spawn(ExampleComponent(0)).id();
let a = Arc::new(Mutex::new(0));
let b = Arc::clone(&a);
world.resource_scope(|w, mut executor: Mut<Executor>| {
executor.add(move |mut fib| async move {
for _ in 0..5 {
let (_, mut example) =
fib.next_tick().then_grab::<&mut ExampleComponent>(e).await;
example.0 += 1;
}
});
executor.add(move |mut fib| async move {
for _ in 0..5 {
let (_, mut example) =
fib.next_tick().then_grab::<&mut ExampleComponent>(e).await;
if false {
example.0 += 1;
}
}
});
executor.add(|mut fib| async move {
loop {
fib.change::<ExampleComponent>(e).await;
*a.lock().unwrap() += 1;
}
});

for i in 0..5 {
executor.tick(w);
assert_eq!(*b.lock().unwrap(), i);
w.clear_trackers();
}
});
}

#[test]
fn waiting_on_internal_and_external_change_is_correct() {
let mut world = World::new();
world.insert_resource(Executor::new());
world.insert_resource(Time::new(Instant::now()));
let e = world.spawn(ExampleComponent(0)).id();
let a = Arc::new(Mutex::new(0));
let b = Arc::clone(&a);
world.resource_scope(|w, mut executor: Mut<Executor>| {
executor.add(move |mut fib| async move {
for _ in 0..5 {
let (_, mut example) =
fib.next_tick().then_grab::<&mut ExampleComponent>(e).await;
example.0 += 1;
}
});
executor.add(move |mut fib| async move {
for _ in 0..5 {
let (_, mut example) =
fib.next_tick().then_grab::<&mut ExampleComponent>(e).await;

if false {
example.0 += 1;
}
}
});
executor.add(|mut fib| async move {
loop {
fib.change::<ExampleComponent>(e).await;
*a.lock().unwrap() += 1;
}
});

for i in 0..5 {
w.entity_mut(e).get_mut::<ExampleComponent>().unwrap().0 += 1;
executor.tick(w);
assert_eq!(*b.lock().unwrap(), i * 2);
w.clear_trackers();
}
});
}
}

0 comments on commit dfd4c2c

Please sign in to comment.