Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions crates/bevy_ecs/src/query/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,46 @@ use std::marker::PhantomData;
/// This is used for ensuring systems are executed soundly.
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Access<T: SparseSetIndex> {
/// Does this access require reading from all values?
reads_all: bool,
/// A combined set of T read and write accesses.
reads_and_writes: FixedBitSet,
/// The values that can be read from
///
/// Note that the ability to write to data implies the ability to read from it,
/// and so this must always be a superset of `writes`.
reads: FixedBitSet,
/// The values that can be written to
writes: FixedBitSet,
marker: PhantomData<T>,
_marker: PhantomData<T>,
}

impl<T: SparseSetIndex> Default for Access<T> {
fn default() -> Self {
Self {
reads_all: false,
reads_and_writes: Default::default(),
reads: Default::default(),
writes: Default::default(),
marker: PhantomData,
_marker: PhantomData,
}
}
}

impl<T: SparseSetIndex> Access<T> {
pub fn grow(&mut self, bits: usize) {
self.reads_and_writes.grow(bits);
self.reads.grow(bits);
self.writes.grow(bits);
}

/// Adds a read access for the given index.
pub fn add_read(&mut self, index: T) {
self.reads_and_writes.grow(index.sparse_set_index() + 1);
self.reads_and_writes.insert(index.sparse_set_index());
self.reads.grow(index.sparse_set_index() + 1);
self.reads.insert(index.sparse_set_index());
}

/// Adds a write access for the given index.
pub fn add_write(&mut self, index: T) {
self.reads_and_writes.grow(index.sparse_set_index() + 1);
self.reads.grow(index.sparse_set_index() + 1);
self.writes.grow(index.sparse_set_index() + 1);
self.reads_and_writes.insert(index.sparse_set_index());
self.reads.insert(index.sparse_set_index());
self.writes.insert(index.sparse_set_index());
}

Expand All @@ -50,7 +55,7 @@ impl<T: SparseSetIndex> Access<T> {
if self.reads_all {
true
} else {
self.reads_and_writes.contains(index.sparse_set_index())
self.reads.contains(index.sparse_set_index())
}
}

Expand All @@ -72,14 +77,14 @@ impl<T: SparseSetIndex> Access<T> {
/// Clears all recorded accesses.
pub fn clear(&mut self) {
self.reads_all = false;
self.reads_and_writes.clear();
self.reads.clear();
self.writes.clear();
}

/// Extends this `Access` with another, copying all accesses of `other` into this.
pub fn extend(&mut self, other: &Access<T>) {
self.reads_all = self.reads_all || other.reads_all;
self.reads_and_writes.union_with(&other.reads_and_writes);
self.reads.union_with(&other.reads);
self.writes.union_with(&other.writes);
}

Expand All @@ -93,8 +98,7 @@ impl<T: SparseSetIndex> Access<T> {
} else if other.reads_all {
0 == self.writes.count_ones(..)
} else {
self.writes.is_disjoint(&other.reads_and_writes)
&& self.reads_and_writes.is_disjoint(&other.writes)
self.writes.is_disjoint(&other.reads) && self.reads.is_disjoint(&other.writes)
}
}

Expand All @@ -108,8 +112,8 @@ impl<T: SparseSetIndex> Access<T> {
if other.reads_all {
conflicts.extend(self.writes.ones());
}
conflicts.extend(self.writes.intersection(&other.reads_and_writes));
conflicts.extend(self.reads_and_writes.intersection(&other.writes));
conflicts.extend(self.writes.intersection(&other.reads));
conflicts.extend(self.reads.intersection(&other.writes));
conflicts
.ones()
.map(SparseSetIndex::get_sparse_set_index)
Expand All @@ -118,7 +122,7 @@ impl<T: SparseSetIndex> Access<T> {

/// Returns all read accesses.
pub fn reads(&self) -> impl Iterator<Item = T> + '_ {
self.reads_and_writes
self.reads
.difference(&self.writes)
.map(T::get_sparse_set_index)
}
Expand Down