#include "event_system.h" #include "aliases.h" #include #include #include #include #define INVALID_LISTENER ((EventListener){ .event = INVALID_EVENT, .id = 0 }) #define IS_INVALID_LISTENER(LS) (LS.id == 0) struct event_system { u64 alloc_size; u64 event_capacity; u64 event_count; u64 free_count; u64 initial_callback_capacity; uptr events_offset; uptr free_offset; uptr callbacks_offset; }; typedef struct event_slot EventSlot; struct event_slot { uptr offset; bool free; }; typedef struct event Event; struct event { u64 capacity; u64 count; EventCallback *callbacks[]; }; void *alloc(u64 size); u32 es_init(EventSystem **es, u64 event_capacity, u64 initial_listeners_capacity) { if (!es) { return ES_INIT_NULL_POINTER; } if (*es) { return ES_INIT_ALREADY_INITIALISED; } u64 callback_capacity = initial_listeners_capacity * 2; u64 system = sizeof(EventSystem); u64 event_slots = event_capacity * sizeof(EventSlot); u64 free_slots = event_capacity * sizeof(u64); u64 events = event_capacity * sizeof(Event); u64 callbacks = event_capacity * callback_capacity * sizeof(EventCallback *); u64 alloc_size = system + event_slots + free_slots + events + callbacks; u8 *buffer = alloc(alloc_size); if (!buffer) { return ES_INIT_ALLOCATION_FAILED; } memset(buffer, 0, alloc_size); *es = (EventSystem *)buffer; EventSystem *event_system = *es; event_system->alloc_size = alloc_size; event_system->event_capacity = event_capacity; event_system->event_count = 0; event_system->free_count = event_capacity; event_system->initial_callback_capacity = callback_capacity; event_system->events_offset = (uptr)system; event_system->free_offset = (uptr)(system + event_slots); event_system->callbacks_offset = (uptr)(system + event_slots + free_slots); EventSlot *ev_slots_ptr = (EventSlot *)((uptr)event_system + event_system->events_offset); u64 *free_slots_ptr = (u64 *)((uptr)event_system + event_system->free_offset); u64 event_item_capacity = sizeof(Event) + callback_capacity * sizeof(EventCallback *); for (u64 i = 0; i < event_capacity; ++i) { free_slots_ptr[i] = event_capacity - (i + 1); ev_slots_ptr[i].offset = event_system->callbacks_offset + i * event_item_capacity; } return ES_INIT_SUCCESS; } void *alloc(u64 size) { return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NORESERVE, -1, 0); } #if 0 struct event_system { EventCallback *callbacks; u64 *callback_count; u64 *free; u64 free_count; u64 event_count; u64 event_capacity; u64 max_listeners_count; }; void *alloc(u64 size); void alloc_members(EventSystem *es, u64 event_capacity); void default_init_event_system(EventSystem *es); bool is_default_initialised(const EventSystem *es); bool member_allocation_failed(const EventSystem *es); u32 es_init(EventSystem **es, u64 event_capacity, u64 initial_listeners_capacity) { if (!es) { return ES_INIT_NULL_POINTER; } if (*es) { return ES_INIT_ALREADY_INITIALISED; } *es = (EventSystem *)alloc(sizeof(EventSystem)); if (!*es) { return ES_INIT_SYSTEM_ALLOC_FAILED; } EventSystem *system = *es; system->free_count = 0; system->event_count = 0; system->event_capacity = event_capacity; system->max_listeners_count = initial_listeners_capacity; alloc_members(system, event_capacity); if (member_allocation_failed(system)) { default_init_event_system(system); return ES_INIT_MEMBER_ALLOC_FAILED; } return ES_INIT_SUCCESS; } void es_deinit(EventSystem **es) { if (!es || !*es) { return; } EventSystem *system = *es; if (!is_default_initialised(system)) { u64 event_capacity = system->event_capacity + 1; munmap(system->callbacks, event_capacity * system->max_listeners_count * sizeof(EventCallback)); munmap(system->callback_count, event_capacity * sizeof(u64)); munmap(system->free, event_capacity * sizeof(u64)); } munmap(system, sizeof(EventSystem)); *es = NULL; } u32 es_register_event(EventSystem *es, u64 id) {} void es_deregister_event(EventSystem *es, u64 id) {} EventListener es_add_event_listener(EventSystem *es, u64 id, EventCallback *listener) {} void es_remove_event_listener(EventSystem *es, EventListener listener) {} void es_emit_event(EventSystem *es, u64 id, void *data) {} void alloc_members(EventSystem *es, u64 event_capacity) { es->callbacks = (EventCallback *)alloc(event_capacity * es->max_listeners_count * sizeof(EventCallback)); es->callback_count = (u64 *)alloc(event_capacity * sizeof(u64)); es->free = (u64 *)alloc(event_capacity * sizeof(u64)); } void default_init_event_system(EventSystem *es) { *es = (EventSystem){0}; es->callbacks = (EventCallback *)es; es->callback_count = (u64 *)es; es->free = (u64 *)es; } bool is_default_initialised(const EventSystem *es) { return es->callbacks == (EventCallback *)es || es->callback_count == (u64 *)es || es->free == (u64 *)es; } bool member_allocation_failed(const EventSystem *es) { return es->callbacks == NULL || es->callback_count == NULL || es->free == NULL; } #endif