use crate::node::ShardRef;
#[derive(Debug, Clone, Default)]
pub struct AccessSet {
pub reads: Vec<ShardRef>,
pub writes: Vec<ShardRef>,
}
impl AccessSet {
pub fn from_node_refs(reads: &[ShardRef], writes: &[ShardRef]) -> Self {
Self {
reads: reads.to_vec(),
writes: writes.to_vec(),
}
}
pub fn conflicts_with(&self, other: &Self) -> bool {
for w_self in &self.writes {
for w_other in &other.writes {
if !w_self.disjoint(*w_other) {
return true;
}
}
}
for r_self in &self.reads {
for w_other in &other.writes {
if !r_self.disjoint(*w_other) {
return true;
}
}
}
for w_self in &self.writes {
for r_other in &other.reads {
if !w_self.disjoint(*r_other) {
return true;
}
}
}
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use evy_ecs_storage::{Namespace, ParticleId};
fn ns(n: Namespace) -> ShardRef {
ShardRef::Namespace(n)
}
fn pa(n: Namespace, idx: u32) -> ShardRef {
ShardRef::Particle(n, ParticleId::from_entity(idx, 0))
}
#[test]
fn read_only_pairs_dont_conflict() {
let a = AccessSet {
reads: vec![ns(Namespace::Coins)],
writes: vec![],
};
let b = AccessSet {
reads: vec![ns(Namespace::Coins)],
writes: vec![],
};
assert!(!a.conflicts_with(&b));
}
#[test]
fn write_write_same_namespace_conflicts() {
let a = AccessSet {
reads: vec![],
writes: vec![ns(Namespace::Coins)],
};
let b = AccessSet {
reads: vec![],
writes: vec![ns(Namespace::Coins)],
};
assert!(a.conflicts_with(&b));
}
#[test]
fn write_write_different_namespaces_dont_conflict() {
let a = AccessSet {
reads: vec![],
writes: vec![ns(Namespace::Coins)],
};
let b = AccessSet {
reads: vec![],
writes: vec![ns(Namespace::Cards)],
};
assert!(!a.conflicts_with(&b));
}
#[test]
fn read_write_overlap_conflicts() {
let reader = AccessSet {
reads: vec![ns(Namespace::Coins)],
writes: vec![],
};
let writer = AccessSet {
reads: vec![],
writes: vec![ns(Namespace::Coins)],
};
assert!(reader.conflicts_with(&writer));
assert!(writer.conflicts_with(&reader));
}
#[test]
fn particle_writes_on_same_namespace_different_particles_dont_conflict() {
let a = AccessSet {
reads: vec![],
writes: vec![pa(Namespace::Particles, 1)],
};
let b = AccessSet {
reads: vec![],
writes: vec![pa(Namespace::Particles, 2)],
};
assert!(!a.conflicts_with(&b));
}
#[test]
fn namespace_write_blocks_any_particle_in_namespace() {
let coarse = AccessSet {
reads: vec![],
writes: vec![ns(Namespace::Particles)],
};
let fine = AccessSet {
reads: vec![pa(Namespace::Particles, 5)],
writes: vec![],
};
assert!(coarse.conflicts_with(&fine));
}
}