186 lines
5.3 KiB
C
186 lines
5.3 KiB
C
#include "event_system.h"
|
|
#include "aliases.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <sys/mman.h>
|
|
|
|
#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
|