diff --git a/src/event_system.c b/src/event_system.c index 2d4f894..38513e9 100644 --- a/src/event_system.c +++ b/src/event_system.c @@ -110,14 +110,16 @@ RETURN_SYSTEM: return es; } -void es_deinit(EventSystem event_system) { - if (IS_INVALID_SYSTEM(event_system)) { +void es_deinit(EventSystem *event_system) { + if (!event_system || IS_INVALID_SYSTEM((*event_system))) { return; } - ESInternal *es = get_event_system_internal(event_system); + ESInternal *es = get_event_system_internal(*event_system); munmap(system, es->alloc_size); + + event_system->id = 0; } Event es_register_event(EventSystem event_system) { @@ -174,11 +176,88 @@ void es_deregister_event(EventSystem event_system, Event event) { } } -EventListener es_add_event_listener(EventSystem event_system, Event event, EventCallback *listener) {} +EventListener es_add_event_listener(EventSystem event_system, Event event, EventCallback callback) { + EventListener listener = INVALID_LISTENER; -void es_remove_event_listener(EventSystem event_system, EventListener listener) {} + if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_EVENT(event) || !callback) { + goto RETURN_LISTENER; + } -void es_emit_event(EventSystem event_system, Event event, void *data) {} + ESInternal *es = get_event_system_internal(event_system); + EventInternal *ev = get_event(es, event); + + if (ev->free_count > 0) { + u64 id = ev->free[--(ev->free_count)]; + + ev->free[ev->free_count] = 0; + ev->callbacks[id] = callback; + + listener.id = id; + listener.event = event; + + goto RETURN_LISTENER; + } + + if (ev->count >= ev->capacity) { + // TODO (Abdelrahman): Handle reallocating when out of callbacks + goto RETURN_LISTENER; + } + + u64 id = ++(ev->count); + + ev->callbacks[id] = callback; + + listener.id = id; + listener.event = event; + +RETURN_LISTENER: + return listener; +} + +void es_remove_event_listener(EventSystem event_system, EventListener listener) { + if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_LISTENER(listener)) { + return; + } + + ESInternal *es = get_event_system_internal(event_system); + EventInternal *ev = get_event(es, listener.event); + + if (listener.id > ev->count) { + return; + } + + if (ev->callbacks[listener.id] == NULL) { + return; + } + + ev->callbacks[listener.id] = NULL; + ev->free[(ev->free_count)++] = listener.id; + + if (listener.id == ev->count) { + ev->count -= 1; + } +} + +void es_emit_event(EventSystem event_system, Event event, void *data) { + if (IS_INVALID_SYSTEM(event_system) || IS_INVALID_EVENT(event)) { + return; + } + + ESInternal *es = get_event_system_internal(event_system); + if (event.id > es->event_count) { + return; + } + + EventInternal *ev = get_event(es, event); + EventCallback callback; + for (int i = 0; i < ev->count; ++i) { + callback = ev->callbacks[i + 1]; + if (!callback) { + continue; + } + callback(data); + } +} // INTERNAL diff --git a/src/event_system.h b/src/event_system.h index 69a153c..cfd4183 100644 --- a/src/event_system.h +++ b/src/event_system.h @@ -25,12 +25,12 @@ struct event_listener { u64 id; }; -typedef void (EventCallback)(void *data); +typedef void (*EventCallback)(void *data); EventSystem es_init(u64 initial_event_capacity, u64 initial_listeners_capacity); -void es_deinit(EventSystem event_system); +void es_deinit(EventSystem *event_system); Event es_register_event(EventSystem event_system); void es_deregister_event(EventSystem event_system, Event event); -EventListener es_add_event_listener(EventSystem event_system, Event event, EventCallback *listener); +EventListener es_add_event_listener(EventSystem event_system, Event event, EventCallback callback); void es_remove_event_listener(EventSystem event_system, EventListener listener); void es_emit_event(EventSystem event_system, Event event, void *data); diff --git a/src/main.c b/src/main.c index 2e23d5f..a98f6c8 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,15 @@ #include "event_system.h" #include +#define ARR_LEN(ARR) (sizeof(ARR) / sizeof(ARR[0])) + +void callback(void *data); +void callback1(void *data); +void callback2(void *data); +void callback3(void *data); +void callback4(void *data); +void callback5(void *data); + int main(void) { EventSystem es = es_init(16, 64); @@ -22,7 +31,72 @@ int main(void) { printf("%lu\n", ev.id); } - es_deinit(es); + printf("\n"); + + es_deregister_event(es, (Event){ .id = 10 }); + Event ev = es_register_event(es); + for (int i = 0; i < 10; ++i) { + EventListener listener = es_add_event_listener(es, ev, callback); + printf("Event: %lu, ID: %lu\n", listener.event.id, listener.id); + } + + printf("\n"); + + for (int i = 5; i < 8; ++i) { + es_remove_event_listener(es, (EventListener){ .event = ev, .id = i }); + } + + for (int i = 0; i < 3; ++i) { + EventListener listener = es_add_event_listener(es, ev, callback); + printf("Event: %lu, ID: %lu\n", listener.event.id, listener.id); + } + + printf("\n"); + + EventCallback callbacks[] = {callback1, callback2, callback3, callback4, callback5}; + EventListener listeners[ARR_LEN(callbacks)] = {0}; + Event ev_with_callbacks = (Event){ .id = 20 }; + for (int i = 0; i < ARR_LEN(callbacks); ++i) { + listeners[i] = es_add_event_listener(es, ev_with_callbacks, callbacks[i]); + } + + es_emit_event(es, ev_with_callbacks, (void *)0); + + printf("\n"); + + es_remove_event_listener(es, listeners[2]); + + es_emit_event(es, ev_with_callbacks, (void *)0); + + printf("\n"); + + printf("SYSTEM: %lu\n", es.id); + es_deinit(&es); + printf("SYSTEM: %lu\n", es.id); return 0; } + +void callback(void *data) { + return; +} + +void callback1(void *data) { + printf("Hello from callback1\n"); +} + +void callback2(void *data) { + printf("Hello from callback2\n"); +} + +void callback3(void *data) { + printf("Hello from callback3\n"); +} + +void callback4(void *data) { + printf("Hello from callback4\n"); +} + +void callback5(void *data) { + printf("Hello from callback5\n"); +}