Skip to content

Commit

Permalink
Merge pull request #232 from Anders429/0.9.1
Browse files Browse the repository at this point in the history
0.9.1
  • Loading branch information
Anders429 authored Aug 10, 2023
2 parents ec18ed4 + 4659c50 commit ec031b2
Show file tree
Hide file tree
Showing 53 changed files with 1,012 additions and 275 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

## 0.9.1 - 2023-08-09
### Fixed
- Dynamic scheduling now respects both `EntryViews` and `ResourceViews`.
- Mutating a deserialized `World` no longer creates duplicate `Archetype`s, instead correctly looking up the existing deserialized `Archetype`.

## 0.9.0 - 2023-04-22
### Changed
- `resource::ContainsViews` now only requires a single generic parameter for indices.
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "brood"
version = "0.9.0"
version = "0.9.1"
authors = ["Anders Evensen"]
edition = "2021"
rust-version = "1.65.0"
Expand All @@ -20,14 +20,14 @@ rustdoc-args = ["--cfg", "doc_cfg"]
[dependencies]
either = {version = "1.8.0", default-features = false}
fnv = {version = "1.0.7", default-features = false}
hashbrown = {version = "0.13.1", default-features = false, features = ["inline-more", "raw"]}
hashbrown = {version = "0.14.0", default-features = false, features = ["inline-more", "raw"]}
rayon = {version = "1.6.0", optional = true}
serde = {version = "1.0.148", default-features = false, features = ["alloc"], optional = true}

[dev-dependencies]
claims = "0.7.1"
rustversion = "1.0.9"
serde_assert = "0.4.0"
serde_assert = "0.5.0"
serde_derive = "1.0.148"
trybuild = "1.0.72"

Expand Down
6 changes: 1 addition & 5 deletions src/archetype/identifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,7 @@ where
R: Registry,
{
fn clone(&self) -> Self {
Self {
registry: PhantomData,

pointer: self.pointer,
}
*self
}
}

Expand Down
74 changes: 37 additions & 37 deletions src/archetypes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,6 @@ where
}
}

/// # Safety
/// `component_map` must contain an entry for each component in the entity `E`. Each entry must
/// correspond to its component's location in the registry `R`.
pub(crate) unsafe fn get_mut_or_insert_new_for_entity<E, P>(&mut self) -> &mut Archetype<R>
where
E: Entity,
Expand All @@ -209,48 +206,51 @@ where
None => unsafe { unreachable_unchecked() },
}
} else {
let identifier = R::create_archetype_identifier();

let hash = Self::make_hash(
// SAFETY: The `IdentifierRef` obtained here does not live longer than the
// `identifier_buffer`.
unsafe { identifier.as_ref() },
&self.hash_builder,
);
// Although type id lookup failed, that doesn't mean the archetype does not exist. We
// instead look up by the raw slice using `foreign_identifier_lookup`.
let identifier_buffer = R::create_archetype_identifier();

if let Some(archetype_bucket) = self.raw_archetypes.find(
hash,
Self::equivalent_identifier(
// SAFETY: The `IdentifierRef` obtained here does not live longer than the
// `identifier_buffer`.
unsafe { identifier.as_ref() },
),
let archetype = if let Some(&identifier) = self.foreign_identifier_lookup.get(
// SAFETY: The slice created here does not outlive the `identifier_buffer`.
unsafe { identifier_buffer.as_slice() },
) {
// SAFETY: This reference to the archetype contained in this bucket is unique.
unsafe { archetype_bucket.as_mut() }
if let Some(archetype) = self.raw_archetypes.get_mut(
Self::make_hash(identifier, &self.hash_builder),
Self::equivalent_identifier(identifier),
) {
archetype
} else {
// SAFETY: Since the identifier was present in `foreign_identifier_lookup`, it
// is guaranteed to have an associated `archetype`.
unsafe { unreachable_unchecked() }
}
} else {
self.type_id_lookup.insert(
TypeId::of::<E>(),
// SAFETY: The `IdentifierRef` obtained here does not live longer than the
// `identifier_buffer`.
unsafe { identifier.as_ref() },
);
// SAFETY: Since the archetype is not contained anywhere in this container, it is
// invariantly guaranteed that the identifier is not contained in
// `foreign_identifier_lookup` either. Additionally, both the slice and
// `IdentifierRef` created here do not outlive `identifier`.
// SAFETY: This identifier has already been verified to not be contained in
// `foreign_identifier_lookup`. Additionally, the slice and `IdentifierRef` created
// here will not outlive the `identifier_buffer`.
unsafe {
self.foreign_identifier_lookup.insert_unique_unchecked(
&*(identifier.as_slice() as *const [u8]),
identifier.as_ref(),
&*(identifier_buffer.as_slice() as *const [u8]),
identifier_buffer.as_ref(),
);
}
self.raw_archetypes.insert_entry(
hash,
Archetype::new(identifier),
// SAFETY: The `IdentifierRef` created here does not outlive the
// `identifier_buffer`.
Self::make_hash(unsafe { identifier_buffer.as_ref() }, &self.hash_builder),
Archetype::new(identifier_buffer),
Self::make_hasher(&self.hash_builder),
)
}
};

self.type_id_lookup.insert(
TypeId::of::<E>(),
// SAFETY: The `IdentifierRef` obtained here does not live longer than the
// `identifier_buffer`.
unsafe { archetype.identifier() },
);

archetype
}
}

Expand Down Expand Up @@ -439,7 +439,7 @@ where
}
}

for (&type_id, identifier) in self.type_id_lookup.iter() {
for (&type_id, identifier) in &self.type_id_lookup {
cloned_archetypes.type_id_lookup.insert(
type_id,
// SAFETY: Each identifier in `self.type_id_lookup` is guaranteed to be found in
Expand Down Expand Up @@ -515,7 +515,7 @@ where
//
// Note that no type id entries are removed here. New ones are just added, since the old
// archetypes were just cleared, not removed entirely.
for (&type_id, identifier) in source.type_id_lookup.iter() {
for (&type_id, identifier) in &source.type_id_lookup {
self.type_id_lookup.insert(
type_id,
// SAFETY: Each identifier in `source.type_id_lookup` is guaranteed to be found in
Expand Down
5 changes: 1 addition & 4 deletions src/entity/allocator/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ where
R: Registry,
{
fn clone(&self) -> Self {
Self {
identifier: self.identifier,
index: self.index,
}
*self
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl<Views, Filters, ResourceViews, EntryViews> Clone
for Query<Views, Filters, ResourceViews, EntryViews>
{
fn clone(&self) -> Self {
Self::new()
*self
}
}

Expand Down
118 changes: 101 additions & 17 deletions src/query/result/archetype_claims.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ use crate::{
archetype,
archetypes,
query::{
filter::And,
view,
view::Claims,
},
registry,
registry::{
contains::filter::Sealed as ContainsFilterSealed,
contains::{
filter::Sealed as ContainsFilterSealed,
views::Sealed as ContainsViewsSealed,
},
ContainsFilter,
ContainsQuery,
ContainsViews,
},
};
use core::marker::PhantomData;
Expand All @@ -19,18 +24,52 @@ use core::marker::PhantomData;
///
/// This iterator returns key-value pairs of archetype identifiers and the list of claimed
/// components for the given query on that archetype.
pub struct ArchetypeClaims<'a, Registry, Filter, Views, Indices>
where
pub struct ArchetypeClaims<
'a,
Registry,
Views,
QueryFilter,
Filter,
EntryViews,
QueryIndices,
FilterIndices,
EntryViewsIndices,
> where
Registry: registry::Registry,
{
archetypes_iter: archetypes::IterMut<'a, Registry>,

views: PhantomData<Views>,
query_filter: PhantomData<QueryFilter>,
filter: PhantomData<Filter>,
view: PhantomData<Views>,
indices: PhantomData<Indices>,
entry_views: PhantomData<EntryViews>,
query_indices: PhantomData<QueryIndices>,
filter_indices: PhantomData<FilterIndices>,
entry_views_indices: PhantomData<EntryViewsIndices>,
}

impl<'a, Registry, Filter, Views, Indices> ArchetypeClaims<'a, Registry, Filter, Views, Indices>
impl<
'a,
Registry,
Views,
QueryFilter,
Filter,
EntryViews,
QueryIndices,
FilterIndices,
EntryViewsIndices,
>
ArchetypeClaims<
'a,
Registry,
Views,
QueryFilter,
Filter,
EntryViews,
QueryIndices,
FilterIndices,
EntryViewsIndices,
>
where
Registry: registry::Registry,
{
Expand All @@ -39,22 +78,51 @@ where
/// # Safety
/// The `archetype::IdentifierRef`s over which this iterator iterates must not outlive the
/// `Archetypes` to which they belong.
///
/// The views and entry views must be compatible with each other.
pub(crate) unsafe fn new(archetypes_iter: archetypes::IterMut<'a, Registry>) -> Self {
Self {
archetypes_iter,

views: PhantomData,
query_filter: PhantomData,
filter: PhantomData,
view: PhantomData,
indices: PhantomData,
entry_views: PhantomData,
query_indices: PhantomData,
filter_indices: PhantomData,
entry_views_indices: PhantomData,
}
}
}

impl<'a, Registry, Filter, Views, Indices> Iterator
for ArchetypeClaims<'a, Registry, Filter, Views, Indices>
impl<
'a,
Registry,
Views,
QueryFilter,
Filter,
EntryViews,
QueryIndices,
FilterIndices,
EntryViewsIndices,
> Iterator
for ArchetypeClaims<
'a,
Registry,
Views,
QueryFilter,
Filter,
EntryViews,
QueryIndices,
FilterIndices,
EntryViewsIndices,
>
where
Views: view::Views<'a>,
Registry: ContainsQuery<'a, Filter, Views, Indices>,
EntryViews: view::Views<'a>,
Registry: ContainsFilter<Filter, FilterIndices>
+ ContainsQuery<'a, QueryFilter, Views, QueryIndices>
+ ContainsViews<'a, EntryViews, EntryViewsIndices>,
{
type Item = (archetype::IdentifierRef<Registry>, Registry::Claims);

Expand All @@ -65,18 +133,34 @@ where
// identifier is generic over. Additionally, the identifier reference created here
// will not outlive `archetype`.
unsafe {
<Registry as ContainsFilterSealed<
And<Views, Filter>,
And<Registry::ViewsFilterIndices, Registry::FilterIndices>,
>>::filter(archetype.identifier())
<Registry as ContainsFilterSealed<Filter, FilterIndices>>::filter(
archetype.identifier(),
)
}
})
.map(|archetype| {
(
// SAFETY: The `IdentifierRef` created here is guaranteed to outlive
// `archetype`, so long as the safety contract at construction is upheld.
unsafe { archetype.identifier() },
Registry::claims(),
// SAFETY: The views and entry views are compatible, meaning merging them is
// always defined.
unsafe {
<Registry as ContainsViewsSealed<
'a,
Views,
(
Registry::ViewsContainments,
Registry::ViewsIndices,
Registry::ViewsCanonicalContainments,
),
>>::claims()
.merge_unchecked(&<Registry as ContainsViewsSealed<
'a,
EntryViews,
EntryViewsIndices,
>>::claims())
},
)
})
}
Expand Down
Loading

0 comments on commit ec031b2

Please sign in to comment.