diff --git a/src/event_system.c b/src/event_system.c index 1c23e9c..ba38d72 100644 --- a/src/event_system.c +++ b/src/event_system.c @@ -5,7 +5,10 @@ #include #include +#define INVALID_EVENT ((Event) { .id = 0 }) #define INVALID_LISTENER ((EventListener){ .event = INVALID_EVENT, .id = 0 }) + +#define IS_INVALID_EVENT(EV) (EV.id == 0) #define IS_INVALID_LISTENER(LS) (LS.id == 0) struct event_system { @@ -22,19 +25,22 @@ struct event_system { typedef struct event_slot EventSlot; struct event_slot { uptr offset; - bool free; + bool registered; }; -typedef struct event Event; -struct event { +typedef struct event_internal EventInternal; +struct event_internal { u64 capacity; u64 count; EventCallback *callbacks[]; }; -void *alloc(u64 size); +void *alloc(u64 size); +EventSlot *get_event_slots_array(const EventSystem *es); +u64 *get_free_array(const EventSystem *es); +EventInternal *get_event(const EventSystem *es, Event event); -u32 es_init(EventSystem **es, u64 event_capacity, u64 initial_listeners_capacity) { +u32 es_init(EventSystem **es, u64 initial_event_capacity, u64 initial_listeners_capacity) { if (!es) { return ES_INIT_NULL_POINTER; } @@ -43,13 +49,19 @@ u32 es_init(EventSystem **es, u64 event_capacity, u64 initial_listeners_capacity 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; + // Double event capacity to reduce chances of reallocation + u64 event_capacity = initial_event_capacity * 2; + // Increase listener capacity by one to account for 0th EventListener being invalid + u64 listeners_capacity = initial_listeners_capacity + 1; + // Double listener capacity to reduce chances of reallocation + u64 callback_capacity = listeners_capacity * 2; + u64 system = sizeof(EventSystem); + // Increase event capacity by one to account for 0th Event being invalid + u64 event_offsets = (event_capacity + 1) * sizeof(EventSlot); + u64 free_slots = event_capacity * sizeof(u64); + u64 events = event_capacity * sizeof(EventInternal); + u64 callbacks = event_capacity * callback_capacity * sizeof(EventCallback *); + u64 alloc_size = system + event_offsets + free_slots + events + callbacks; u8 *buffer = alloc(alloc_size); if (!buffer) { @@ -65,70 +77,17 @@ u32 es_init(EventSystem **es, u64 event_capacity, u64 initial_listeners_capacity 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->free_count = 0; + event_system->initial_callback_capacity = callback_capacity - 1; event_system->events_offset = (uptr)system; - event_system->free_offset = (uptr)(system + event_slots); - event_system->callbacks_offset = (uptr)(system + event_slots + free_slots); + event_system->free_offset = (uptr)(system + event_offsets); + event_system->callbacks_offset = (uptr)(system + event_offsets + 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); + EventSlot *ev_slots_array = get_event_slots_array(event_system); - u64 event_item_capacity = sizeof(Event) + callback_capacity * sizeof(EventCallback *); + u64 event_item_capacity = sizeof(EventInternal) + 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; + ev_slots_array[i].offset = event_system->callbacks_offset + i * event_item_capacity; } return ES_INIT_SUCCESS; @@ -141,20 +100,56 @@ void es_deinit(EventSystem **es) { 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)); + munmap(system, system->alloc_size); *es = NULL; } -u32 es_register_event(EventSystem *es, u64 id) {} +Event es_register_event(EventSystem *es) { + Event event = INVALID_EVENT; -void es_deregister_event(EventSystem *es, u64 id) {} + if (!es) { + goto RETURN_EVENT; + } + + EventSlot *event_slots_array = get_event_slots_array(es); + + if (es->free_count > 0) { + u64 *free_array = get_free_array(es); + + event.id = free_array[--(es->free_count)]; + event_slots_array[event.id].registered = true; + + free_array[es->free_count] = 0; + + goto RETURN_EVENT; + } + + if (es->event_count >= es->event_capacity) { + goto RETURN_EVENT; + } + + event.id = ++(es->event_count); + event_slots_array[event.id].registered = true; + +RETURN_EVENT: + return event; +} + +void es_deregister_event(EventSystem *es, Event event) { + if (!es || IS_INVALID_EVENT(event)) { + return; + } + + EventSlot *event_slots_array = get_event_slots_array(es); + u64 *free_array = get_free_array(es); + + event_slots_array[event.id].registered = false; + free_array[(es->free_count)++] = event.id; + + if (event.id == es->event_count) { + es->event_count -= 1; + } +} EventListener es_add_event_listener(EventSystem *es, u64 id, EventCallback *listener) {} @@ -162,24 +157,21 @@ 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)); +// INTERNAL + +void *alloc(u64 size) { + return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NORESERVE, -1, 0); } -void default_init_event_system(EventSystem *es) { - *es = (EventSystem){0}; - es->callbacks = (EventCallback *)es; - es->callback_count = (u64 *)es; - es->free = (u64 *)es; +EventSlot *get_event_slots_array(const EventSystem *es) { + return (EventSlot *)((uptr)es + es->events_offset); } -bool is_default_initialised(const EventSystem *es) { - return es->callbacks == (EventCallback *)es || es->callback_count == (u64 *)es || es->free == (u64 *)es; +u64 *get_free_array(const EventSystem *es) { + return (u64 *)((uptr)es + es->free_offset); } -bool member_allocation_failed(const EventSystem *es) { - return es->callbacks == NULL || es->callback_count == NULL || es->free == NULL; +EventInternal *get_event(const EventSystem *es, Event event) { + EventSlot *event_slots_array = get_event_slots_array(es); + return (EventInternal *)((uptr)es + event_slots_array[event.id].offset); } -#endif diff --git a/src/event_system.h b/src/event_system.h index 5259c5a..19a14a7 100644 --- a/src/event_system.h +++ b/src/event_system.h @@ -9,9 +9,14 @@ enum { ES_INIT_ALLOCATION_FAILED, }; +typedef struct event Event; +struct event { + u64 id; +}; + typedef struct event_listener EventListener; struct event_listener { - u64 event; + Event event; u64 id; }; @@ -19,10 +24,10 @@ typedef struct event_system EventSystem; typedef void (EventCallback)(void *data); -u32 es_init(EventSystem **es, u64 event_capacity, u64 initial_event_listeners_count); +u32 es_init(EventSystem **es, u64 initial_event_capacity, u64 initial_listeners_capacity); void es_deinit(EventSystem **es); -u32 es_register_event(EventSystem *es, u64 id); -void es_deregister_event(EventSystem *es, u64 id); +Event es_register_event(EventSystem *es); +void es_deregister_event(EventSystem *es, Event event); 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); diff --git a/src/main.c b/src/main.c index ede722d..a674604 100644 --- a/src/main.c +++ b/src/main.c @@ -4,12 +4,30 @@ int main(void) { EventSystem *es = NULL; - if (es_init(&es, 32, 64) != ES_INIT_SUCCESS) { + if (es_init(&es, 16, 64) != ES_INIT_SUCCESS) { printf("INITIALISATION FAILED\n"); return 1; } - // es_deinit(&es); + for (int i = 0; i < 40; ++i) { + Event ev = es_register_event(es); + printf("%lu\n", ev.id); + } + + printf("\n"); + + unsigned int count = 6; + + for (int i = 0; i < count; ++i) { + es_deregister_event(es, (Event){ .id = (i + 1) * 2 }); + } + + for (int i = 0; i < count; ++i) { + Event ev = es_register_event(es); + printf("%lu\n", ev.id); + } + + es_deinit(&es); return 0; }