Handle reallocating when out of events
This commit is contained in:
parent
7021b7a401
commit
8b3216f416
@ -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;
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ struct event_system {
|
||||
|
||||
typedef struct event Event;
|
||||
struct event {
|
||||
EventSystem system;
|
||||
u64 id;
|
||||
};
|
||||
|
||||
|
@ -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]);
|
||||
|
Loading…
Reference in New Issue
Block a user