From 8b3216f416bc39a8907a8116d9425434d186f25f Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sat, 25 Jan 2025 23:08:04 +0000 Subject: [PATCH] Handle reallocating when out of events --- src/event_system.c | 69 ++++++++++++++++++++++++++++++++++++++-------- src/event_system.h | 1 - src/main.c | 8 ++++++ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/event_system.c b/src/event_system.c index c1b3e16..8f593fd 100644 --- a/src/event_system.c +++ b/src/event_system.c @@ -17,6 +17,9 @@ #define IS_INVALID_EVENT(EV) (EV.id == 0) #define IS_INVALID_LISTENER(LS) (LS.id == 0 || IS_INVALID_EVENT(LS.event)) +#define CB_ARR_SIZE(CAPACITY) ((CAPACITY + 1) * sizeof(EventCallback *)) +#define FREE_CB_ARR_SIZE(CAPACITY) (CAPACITY * sizeof(u64 *)) + typedef struct es_internal ESInternal; struct es_internal { u64 magic; @@ -49,8 +52,10 @@ internal void *alloc(u64 size); internal ESInternal *get_event_system_internal(EventSystem event_system); internal EventSlot *get_event_slots_array(const ESInternal *es); internal u64 *get_free_array(const ESInternal *es); +internal void copy_event_data(const ESInternal *src, ESInternal *dst); internal EventInternal *get_event(const ESInternal *es, Event event); internal EventInternal *get_event_from_offset(const ESInternal *es, u64 offset); +internal u64 get_largest_capacity(const ESInternal *es); EventSystem es_init(u64 initial_event_capacity, u64 initial_listeners_capacity) { // Double event capacity to reduce chances of reallocation @@ -62,9 +67,9 @@ EventSystem es_init(u64 initial_event_capacity, u64 initial_listeners_capacity) u64 event_offsets = (event_capacity + 1) * sizeof(EventSlot); u64 free_slots = event_capacity * sizeof(u64); u64 events = event_capacity * sizeof(EventInternal); - // Increase listener capacity by one to account for 0th EventListener being invalid - u64 event_callbacks = (callback_capacity + 1) * sizeof(EventCallback *); - u64 event_free = callback_capacity * sizeof(u64 *); + // Increases listener capacity by one to account for 0th EventListener being invalid + u64 event_callbacks = CB_ARR_SIZE(callback_capacity); + u64 event_free = FREE_CB_ARR_SIZE(callback_capacity); u64 callbacks = event_capacity * event_callbacks; u64 free_callbacks = event_capacity * event_free; u64 alloc_size = system + event_offsets + free_slots + events + callbacks + free_callbacks; @@ -143,8 +148,6 @@ Event es_register_event(EventSystem *event_system) { goto RETURN_EVENT; } - event.system = *event_system; - EventSlot *event_slots_array = get_event_slots_array(es); if (es->free_count > 0) { @@ -159,8 +162,17 @@ Event es_register_event(EventSystem *event_system) { } if (es->event_count >= es->event_capacity) { - // TODO (Abdelrahman): Handle reallocating when out of events - goto RETURN_EVENT; + u64 new_callback_capacity = get_largest_capacity(es); + EventSystem event_system_new = es_init(es->event_capacity, new_callback_capacity); + ESInternal *es_new = get_event_system_internal(event_system_new); + + es_new->event_count = es->event_count; + + copy_event_data(es, es_new); + + es_deinit(event_system); + event_system->id = (u64)es_new; + es = es_new; } event.id = ++(es->event_count); @@ -171,7 +183,7 @@ RETURN_EVENT: } void es_deregister_event(EventSystem event_system, Event *event) { - if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_EVENT((*event)) || event_system.id != event->system.id) { + if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_EVENT((*event))) { return; } @@ -196,7 +208,7 @@ void es_deregister_event(EventSystem event_system, Event *event) { EventListener es_add_event_listener(EventSystem *event_system, Event event, EventCallback callback) { EventListener listener = INVALID_LISTENER; - if (!event_system || IS_INVALID_SYSTEM((*event_system)) || IS_INVALID_EVENT(event) || event_system->id != event.system.id || !callback) { + if (!event_system || IS_INVALID_SYSTEM((*event_system)) || IS_INVALID_EVENT(event) || !callback) { goto RETURN_LISTENER; } @@ -236,7 +248,7 @@ RETURN_LISTENER: } void es_remove_event_listener(EventSystem event_system, EventListener listener) { - if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_LISTENER(listener) || event_system.id != listener.event.system.id) { + if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_LISTENER(listener)) { return; } @@ -264,7 +276,7 @@ void es_remove_event_listener(EventSystem event_system, EventListener listener) } void es_emit_event(EventSystem event_system, Event event, void *data) { - if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_EVENT(event) || event_system.id != event.system.id) { + if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_EVENT(event)) { return; } @@ -302,6 +314,26 @@ internal u64 *get_free_array(const ESInternal *es) { return (u64 *)((uptr)es + es->free_offset); } +internal void copy_event_data(const ESInternal *src, ESInternal *dst) { + EventSlot *slots_src = get_event_slots_array(src); + EventSlot *slots_dst = get_event_slots_array(dst); + + EventInternal *ev_src; + EventInternal *ev_dst; + for (u64 i = 1; i <= src->event_count; ++i) { + slots_dst[i].registered = slots_src[i].registered; + + ev_src = get_event_from_offset(src, slots_src[i].offset); + ev_dst = get_event_from_offset(dst, slots_dst[i].offset); + + ev_dst->count = ev_src->count; + ev_dst->free_count = ev_src->free_count; + + memcpy((void *)(ev_dst->free), (void *)(ev_src->free), FREE_CB_ARR_SIZE(ev_src->capacity)); + memcpy((void *)(ev_dst->callbacks), (void *)(ev_src->callbacks), CB_ARR_SIZE(ev_src->capacity)); + } +} + internal EventInternal *get_event(const ESInternal *es, Event event) { EventSlot *event_slots_array = get_event_slots_array(es); return get_event_from_offset(es, event_slots_array[event.id].offset); @@ -310,3 +342,18 @@ internal EventInternal *get_event(const ESInternal *es, Event event) { internal EventInternal *get_event_from_offset(const ESInternal *es, u64 offset) { return (EventInternal *)((uptr)es + offset); } + +internal u64 get_largest_capacity(const ESInternal *es) { + EventSlot *event_slots_array = get_event_slots_array(es); + u64 capacity = es->initial_callback_capacity; + + EventInternal *event; + for (u64 i = 1; i <= es->event_count; ++i) { + event = get_event_from_offset(es, event_slots_array[i].offset); + if (event->capacity > capacity) { + capacity = event->capacity; + } + } + + return capacity; +} diff --git a/src/event_system.h b/src/event_system.h index c938699..9e437a0 100644 --- a/src/event_system.h +++ b/src/event_system.h @@ -16,7 +16,6 @@ struct event_system { typedef struct event Event; struct event { - EventSystem system; u64 id; }; diff --git a/src/main.c b/src/main.c index 3727218..fec4e14 100644 --- a/src/main.c +++ b/src/main.c @@ -67,6 +67,14 @@ int main(void) { es_remove_event_listener(es, listener); es_deregister_event(es, &extra_event); + for (int i = 0; i < 10; ++i) { + es_register_event(&es); + } + + es_emit_event(es, events[EVENT_WINDOW], (void *)&window_event); + es_emit_event(es, events[EVENT_KEYBOARD], (void *)&keyboard_event); + es_emit_event(es, events[EVENT_MOUSE], (void *)&mouse_event); + for (int i = 0; i < COUNT_EVENTS; ++i) { es_remove_event_listener(es, listeners[i]); es_deregister_event(es, &events[i]);