rj00a / evenio

An event-driven Entity Component System
MIT License
137 stars 14 forks source link

feat: make `Sender` state publicly accessible #69

Open andrewgazelka opened 5 months ago

andrewgazelka commented 5 months ago

This is useful for having a way to prepare events in a multi-threaded context before actually sending them in a single-threaded context.

// todo: I'd love to see if we actually need the two lifetimes or not.
// We might be able to just use one for both of them, but I never really figure out when I need one versus two.
struct SenderLocal<'a, 'b, ES: EventSet> {
    state: &'b ES::Indices,
    bump: &'a Bump,
    pending_write: Vec<(NonNull<u8>, GlobalEventIdx)>,
}

impl<'a, 'b, ES: EventSet> SenderLocal<'a, 'b, ES> {
    pub fn new(state: &'b ES::Indices, bump: &'a Bump) -> Self {
        Self {
            state,
            bump,

            // todo: Potentially, this should be under bump allocator, but let's profile before trying to do that.
            pending_write: Vec::new(),
        }
    }

    // todo: what does track caller do?
    #[track_caller]
    pub fn send<E: GlobalEvent + 'static>(&mut self, event: E) {
        // The event type and event set are all compile time known, so the compiler
        // should be able to optimize this away.
        let event_idx = ES::find_index::<E>(self.state).unwrap_or_else(|| {
            panic!(
                "global event `{}` is not in the `EventSet` of this `Sender`",
                any::type_name::<E>()
            )
        });

        // let ptr = self.alloc_layout(Layout::new::<E>());
        let ptr = self.bump.alloc_layout(Layout::new::<E>());

        unsafe { ptr::write::<E>(ptr.as_ptr().cast(), event) };

        // This will be saved until the end of the system, where we will be sending the events in one thread synchronously.
        // unsafe { self.world.queue_global(ptr, GlobalEventIdx(event_idx)) };
        self.pending_write.push((ptr, GlobalEventIdx(event_idx)));
    }
}
andrewgazelka commented 5 months ago

todo: docs

andrewgazelka commented 5 months ago

Okay, I added docs. I don't know exactly what you want because I don't know the specifics.

andrewgazelka commented 5 months ago

I also made UnsafeWorldCell obtainable. I don't know if this is something you want, but I definitely need it. I don't know if it can be obtained through a handler as well.

andrewgazelka commented 5 months ago

Actually, I didn't end up needing to flush.