Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug in event broadcasting #12

Merged
merged 3 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## Unreleased

- Fixed a bug in event propagation.
- The behavior of the event queue has changed. The next event in the queue is handled only once the current event has finished broadcasting.
- Changed `EventPtr` interface and relaxed `Send` and `Sync` bounds for `EventMut`.

## 0.2.2 - 2024-02-8

- Update documentation
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ It aims to have a small but maximally expressive set of features that are easy a

## Features

- In addition to the usual Entities, Components, and Systems, `evenio` introduces _events_ as a first-class citizen.
Rather than restricting systems to run once every frame/update in a fixed order, systems are generalized as _event handlers_.
- In addition to the usual Entities, Components, and Systems, `evenio` introduces events as a first-class citizen.
Rather than restricting systems to run once every frame/update in a fixed order, systems are generalized as event handlers.
The control flow of the entire program is then defined by the flow of events between systems.
- Structural changes to the world (such as entity despawning, component additions/removals, etc.) are mediated by events, allowing systems to hook into their occurrence.
- _Targeted events_ enable systems to efficiently filter events based on queries.
- Targeted events enable systems to efficiently filter events based on queries.
- Component types, event types, and systems are identified with generational indices, allowing them to be added and removed dynamically.
- Execute systems in parallel with [Rayon].
- Core of the library does not depend on Rust's type system.
Expand Down
6 changes: 5 additions & 1 deletion src/archetype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use core::cmp::Ordering;
use core::ptr;
use core::ptr::NonNull;

use ahash::RandomState;
use slab::Slab;

use crate::assert::{assume_debug_checked, GetDebugChecked, UnwrapDebugChecked};
Expand Down Expand Up @@ -47,9 +48,12 @@ pub struct Archetypes {

impl Archetypes {
pub(crate) fn new() -> Self {
let mut map = HashMap::with_hasher(RandomState::new());
map.insert(vec![].into_boxed_slice(), ArchetypeIdx::EMPTY);

Self {
archetypes: Slab::from_iter([(0, Archetype::empty())]),
by_components: HashMap::from_iter([(vec![].into_boxed_slice(), ArchetypeIdx::EMPTY)]),
by_components: map,
}
}

Expand Down
37 changes: 12 additions & 25 deletions src/assert.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Utilities for runtime and compile-time assertions.

use alloc::vec::Vec;
use core::marker::PhantomData;
use core::slice::SliceIndex;
use core::{fmt, mem};

use slab::Slab;
Expand All @@ -16,7 +16,7 @@ const _: () = assert!(

/// Extension trait for checked array indexing with checks removed in release
/// mode.
pub(crate) trait GetDebugChecked {
pub(crate) trait GetDebugChecked<Idx> {
type Output: ?Sized;

/// Gets a reference to the element at the given index.
Expand All @@ -28,7 +28,7 @@ pub(crate) trait GetDebugChecked {
///
/// - `idx` must be in bounds.
#[track_caller]
unsafe fn get_debug_checked(&self, idx: usize) -> &Self::Output;
unsafe fn get_debug_checked(&self, idx: Idx) -> &Self::Output;
/// Gets a mutable reference to the element at the given index.
///
/// If `idx` is not in bounds, a panic occurs in debug mode and Undefined
Expand All @@ -38,23 +38,24 @@ pub(crate) trait GetDebugChecked {
///
/// - `idx` must be in bounds.
#[track_caller]
unsafe fn get_debug_checked_mut(&mut self, idx: usize) -> &mut Self::Output;
unsafe fn get_debug_checked_mut(&mut self, idx: Idx) -> &mut Self::Output;
}

impl<T> GetDebugChecked for [T] {
type Output = T;
impl<T, I> GetDebugChecked<I> for [T]
where
I: SliceIndex<[T]>,
{
type Output = I::Output;

#[inline]
unsafe fn get_debug_checked(&self, idx: usize) -> &Self::Output {
unsafe fn get_debug_checked(&self, idx: I) -> &Self::Output {
#[cfg(debug_assertions)]
return &self[idx];

#[cfg(not(debug_assertions))]
return self.get_unchecked(idx);
}

#[inline]
unsafe fn get_debug_checked_mut(&mut self, idx: usize) -> &mut Self::Output {
unsafe fn get_debug_checked_mut(&mut self, idx: I) -> &mut Self::Output {
#[cfg(debug_assertions)]
return &mut self[idx];

Expand All @@ -63,22 +64,8 @@ impl<T> GetDebugChecked for [T] {
}
}

impl<T> GetDebugChecked for Vec<T> {
type Output = T;

#[inline]
unsafe fn get_debug_checked(&self, idx: usize) -> &Self::Output {
self.as_slice().get_debug_checked(idx)
}

#[inline]
unsafe fn get_debug_checked_mut(&mut self, idx: usize) -> &mut Self::Output {
self.as_mut_slice().get_debug_checked_mut(idx)
}
}

// Don't use `Slab::get_unchecked` because there's a panicking branch. https://github.com/tokio-rs/slab/pull/74
impl<T> GetDebugChecked for Slab<T> {
impl<T> GetDebugChecked<usize> for Slab<T> {
type Output = T;

#[inline]
Expand Down
3 changes: 0 additions & 3 deletions src/blob_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ impl BlobVec {
/// - `drop` must be safe to call with elements of this `BlobVec` as
/// described by [`DropFn`]'s documentation.
pub(crate) unsafe fn new(layout: Layout, drop: DropFn) -> Self {
// // SAFETY: `Layout` guarantees alignment is non-zero.
// let data = NonNull::new(layout.align() as *mut u8).unwrap_debug_checked();

Self {
elem_layout: pad_to_align(&layout),
len: 0,
Expand Down
Loading
Loading