352#define queued_emitter_enqueue(qe, event, ptr) \
353 (queued_emitter_enqueue_raw((qe), (event), (ptr), sizeof(*(ptr))))
380#ifdef PICO_EMITTER_IMPLEMENTATION
390#ifndef PICO_EMITTER_INIT_CAPACITY
391 #define PICO_EMITTER_INIT_CAPACITY 8
395 #define PICO_EMITTER_ASSERT(expr) ((void)0)
397 #ifndef PICO_EMITTER_ASSERT
399 #define PICO_EMITTER_ASSERT(expr) assert(expr)
403#ifndef PICO_EMITTER_MALLOC
405 #define PICO_EMITTER_MALLOC(size) malloc(size)
406 #define PICO_EMITTER_REALLOC(p, sz) realloc(p, sz)
407 #define PICO_EMITTER_FREE(ptr) free(ptr)
410#ifndef PICO_EMITTER_MEMCPY
412 #define PICO_EMITTER_MEMCPY(dst, src, n) memcpy(dst, src, n)
415#ifndef PICO_EMITTER_MEMSET
417 #define PICO_EMITTER_MEMSET(dst, val, n) memset(dst, val, n)
424#define EMITTER_INIT_CAPACITY PICO_EMITTER_INIT_CAPACITY
425#define EMITTER_ASSERT PICO_EMITTER_ASSERT
426#define EMITTER_MALLOC PICO_EMITTER_MALLOC
427#define EMITTER_REALLOC PICO_EMITTER_REALLOC
428#define EMITTER_FREE PICO_EMITTER_FREE
429#define EMITTER_MEMCPY PICO_EMITTER_MEMCPY
430#define EMITTER_MEMSET PICO_EMITTER_MEMSET
453 emitter_slot_t* events;
461typedef struct arena_block_s
466 struct arena_block_s* next;
469typedef struct arena_s
471 arena_block_t* first;
472 arena_block_t* current;
480static void emitter_grow_slot(emitter_slot_t* slot);
481static void emitter_compact(emitter_slot_t* slot);
484static arena_block_t* arena_block_create(
size_t size);
485static bool arena_init(arena_t* arena,
size_t initial_block_size);
486static bool arena_grow(arena_t* arena,
size_t min_size);
487static uintptr_t arena_align_forward(uintptr_t ptr,
size_t align);
488static void* arena_alloc_align(arena_t* arena,
size_t size,
size_t align);
489static void* arena_alloc(arena_t* arena,
size_t size);
490static void arena_reset(arena_t* arena);
491static void arena_destroy(arena_t* arena);
499 EMITTER_ASSERT(num_events > 0);
508 emitter->events = (emitter_slot_t*)EMITTER_MALLOC((
size_t)num_events *
sizeof(emitter_slot_t));
510 if (!emitter->events)
512 EMITTER_FREE(emitter);
516 EMITTER_MEMSET(emitter->events, 0, (
size_t)num_events *
sizeof(emitter_slot_t));
518 emitter->num_events = num_events;
525 EMITTER_ASSERT(emitter != NULL);
527 for (
int i = 0; i < emitter->num_events; i++)
529 EMITTER_FREE(emitter->events[i].listeners);
530 EMITTER_FREE(emitter->events[i].udatas);
531 EMITTER_FREE(emitter->events[i].once);
534 EMITTER_FREE(emitter->events);
535 EMITTER_FREE(emitter);
540 EMITTER_ASSERT(emitter != NULL);
541 EMITTER_ASSERT(num_events > 0);
543 int old_num = emitter->num_events;
545 if (num_events == old_num)
552 for (
int i = num_events; i < old_num; i++)
554 EMITTER_FREE(emitter->events[i].listeners);
555 EMITTER_FREE(emitter->events[i].udatas);
556 EMITTER_FREE(emitter->events[i].once);
559 EMITTER_MEMSET(&emitter->events[i], 0,
sizeof(emitter_slot_t));
562 emitter_slot_t* events = (emitter_slot_t*)EMITTER_REALLOC(emitter->events, (
size_t)num_events *
sizeof(emitter_slot_t));
570 if (num_events > old_num)
572 EMITTER_MEMSET(&events[old_num], 0, (
size_t)(num_events - old_num) *
sizeof(emitter_slot_t));
575 emitter->events = events;
576 emitter->num_events = num_events;
583 emitter_subscribe(emitter, event, listener, udata,
false);
588 emitter_subscribe(emitter, event, listener, udata,
true);
593 EMITTER_ASSERT(emitter != NULL);
594 EMITTER_ASSERT(event >= 0 && event < emitter->num_events);
595 EMITTER_ASSERT(listener != NULL);
597 emitter_slot_t* slot = &emitter->events[event];
599 for (
int i = 0; i < slot->count; i++)
601 if (slot->listeners[i] != listener)
609 slot->listeners[i] = NULL;
614 for (
int j = i; j < slot->count - 1; j++)
616 slot->listeners[j] = slot->listeners[j + 1];
617 slot->udatas[j] = slot->udatas[j + 1];
618 slot->once[j] = slot->once[j + 1];
630 EMITTER_ASSERT(emitter != NULL);
631 EMITTER_ASSERT(event >= 0 && event < emitter->num_events);
633 emitter_slot_t* slot = &emitter->events[event];
638 for (
int i = 0; i < slot->count; i++)
640 slot->listeners[i] = NULL;
651 EMITTER_ASSERT(emitter != NULL);
652 EMITTER_ASSERT(event >= 0 && event < emitter->num_events);
654 emitter_slot_t* slot = &emitter->events[event];
660 int count = slot->count;
661 bool needs_compact =
false;
663 slot->emitting =
true;
665 for (
int i = 0; i < count; i++)
672 needs_compact =
true;
682 slot->listeners[i] = NULL;
683 needs_compact =
true;
686 fn(data, slot->udatas[i]);
693 if (slot->listeners[i] == NULL)
695 needs_compact =
true;
699 slot->emitting =
false;
703 emitter_compact(slot);
709 EMITTER_ASSERT(emitter != NULL);
710 EMITTER_ASSERT(event >= 0 && event < emitter->num_events);
712 return emitter->events[event].count;
719struct queued_emitter_s
736 EMITTER_ASSERT(num_events > 0);
753 size_t init_block = (size_t)EMITTER_INIT_CAPACITY *
sizeof(
void*);
755 if (!arena_init(&qe->arenas[0], init_block))
762 if (!arena_init(&qe->arenas[1], init_block))
764 arena_destroy(&qe->arenas[0]);
781 EMITTER_ASSERT(qe != NULL);
784 arena_destroy(&qe->arenas[0]);
785 arena_destroy(&qe->arenas[1]);
786 EMITTER_FREE(qe->events);
787 EMITTER_FREE(qe->datas);
793 EMITTER_ASSERT(qe != NULL);
799 EMITTER_ASSERT(qe != NULL);
800 emitter_on(qe->emitter, event, listener, udata);
805 EMITTER_ASSERT(qe != NULL);
811 EMITTER_ASSERT(qe != NULL);
817 EMITTER_ASSERT(qe != NULL);
823 EMITTER_ASSERT(qe != NULL);
829 EMITTER_ASSERT(qe != NULL);
830 EMITTER_ASSERT(event >= 0 && event < qe->emitter->num_events);
832 if (qe->count == qe->capacity)
834 queued_emitter_grow(qe);
837 const void* stored = NULL;
839 if (data != NULL && data_size > 0)
841 void* copy = arena_alloc(&qe->arenas[qe->write_arena], data_size);
842 EMITTER_ASSERT(copy != NULL);
843 EMITTER_MEMCPY(copy, data, data_size);
847 qe->events[qe->count] = event;
848 qe->datas[qe->count] = stored;
854 EMITTER_ASSERT(qe != NULL);
860 int flush_count = qe->count;
861 int read_arena = qe->write_arena;
866 qe->write_arena = 1 - read_arena;
868 for (
int i = 0; i < flush_count; i++)
875 remaining = qe->count - flush_count;
877 for (
int i = 0; i < remaining; i++)
879 qe->events[i] = qe->events[flush_count + i];
880 qe->datas[i] = qe->datas[flush_count + i];
883 qe->count = remaining;
886 arena_reset(&qe->arenas[read_arena]);
888 }
while (remaining > 0);
893 EMITTER_ASSERT(qe != NULL);
904static void emitter_grow_slot(emitter_slot_t* slot)
906 int new_cap = slot->capacity == 0 ? EMITTER_INIT_CAPACITY : slot->capacity * 2;
909 void** u = (
void**) EMITTER_REALLOC(slot->udatas, (
size_t)new_cap *
sizeof(
void*));
910 bool* o = (
bool*) EMITTER_REALLOC(slot->once, (
size_t)new_cap *
sizeof(bool));
912 EMITTER_ASSERT(l != NULL);
913 EMITTER_ASSERT(u != NULL);
914 EMITTER_ASSERT(o != NULL);
919 slot->capacity = new_cap;
925static void emitter_compact(emitter_slot_t* slot)
929 for (
int src = 0; src < slot->count; src++)
931 if (slot->listeners[src] != NULL)
933 slot->listeners[dst] = slot->listeners[src];
934 slot->udatas[dst] = slot->udatas[src];
935 slot->once[dst] = slot->once[src];
946static void emitter_subscribe(
emitter_t* emitter,
int event,
950 EMITTER_ASSERT(emitter != NULL);
951 EMITTER_ASSERT(event >= 0 && event < emitter->num_events);
952 EMITTER_ASSERT(listener != NULL);
954 emitter_slot_t* slot = &emitter->events[event];
956 if (slot->count == slot->capacity)
958 emitter_grow_slot(slot);
961 slot->listeners[slot->count] = listener;
962 slot->udatas[slot->count] = udata;
963 slot->once[slot->count] = once;
973 int new_cap = qe->capacity == 0 ? EMITTER_INIT_CAPACITY : qe->capacity * 2;
975 int* events = (
int*) EMITTER_REALLOC(qe->events, (
size_t)new_cap *
sizeof(int));
976 const void** datas = (
const void**)EMITTER_REALLOC(qe->datas, (
size_t)new_cap *
sizeof(
const void*));
978 EMITTER_ASSERT(events != NULL);
979 EMITTER_ASSERT(datas != NULL);
983 qe->capacity = new_cap;
990static arena_block_t* arena_block_create(
size_t size)
992 arena_block_t* block = (arena_block_t*)EMITTER_MALLOC(
sizeof(arena_block_t));
997 block->memory = (uint8_t*)EMITTER_MALLOC(size);
1001 EMITTER_FREE(block);
1012static bool arena_init(arena_t* arena,
size_t initial_block_size)
1014 arena_block_t* block = arena_block_create(initial_block_size);
1019 arena->first = block;
1020 arena->current = block;
1021 arena->block_size = initial_block_size;
1026static bool arena_grow(arena_t* arena,
size_t min_size)
1028 size_t new_size = arena->block_size;
1030 while (new_size < min_size)
1035 arena_block_t* block = arena_block_create(new_size);
1040 arena->current->next = block;
1041 arena->current = block;
1046static uintptr_t arena_align_forward(uintptr_t ptr,
size_t align)
1048 uintptr_t mask = (uintptr_t)align - 1;
1049 return (ptr + mask) & ~mask;
1052static void* arena_alloc_align(arena_t* arena,
size_t size,
size_t align)
1054 if ((align & (align - 1)) != 0)
1057 arena_block_t* block = arena->current;
1059 uintptr_t base = (uintptr_t)block->memory;
1060 uintptr_t ptr = base + block->offset;
1061 uintptr_t aligned = arena_align_forward(ptr, align);
1062 size_t new_offset = (aligned - base) + size;
1064 if (new_offset > block->size)
1066 size_t required = size + align;
1068 if (!arena_grow(arena, required))
1071 block = arena->current;
1072 base = (uintptr_t)block->memory;
1073 aligned = arena_align_forward(base, align);
1074 new_offset = (aligned - base) + size;
1077 block->offset = new_offset;
1079 return (
void*)aligned;
1082static void* arena_alloc(arena_t* arena,
size_t size)
1084 return arena_alloc_align(arena, size,
alignof(max_align_t));
1087static void arena_reset(arena_t* arena)
1089 arena_block_t* block = arena->first->next;
1093 arena_block_t* next = block->next;
1094 EMITTER_FREE(block->memory);
1095 EMITTER_FREE(block);
1099 arena->first->next = NULL;
1100 arena->first->offset = 0;
1101 arena->current = arena->first;
1104static void arena_destroy(arena_t* arena)
1106 arena_block_t* block = arena->first;
1110 arena_block_t* next = block->next;
1111 EMITTER_FREE(block->memory);
1112 EMITTER_FREE(block);
1116 arena->first = NULL;
1117 arena->current = NULL;
int queued_emitter_count(const queued_emitter_t *qe, int event)
Returns the number of listeners currently subscribed to an event.
void queued_emitter_off(queued_emitter_t *qe, int event, emitter_listener_fn listener)
Unsubscribes the first listener whose function pointer matches.
void queued_emitter_enqueue_raw(queued_emitter_t *qe, int event, const void *data, size_t data_size)
Enqueues an event for deferred dispatch.
struct emitter_s emitter_t
Event emitter context (opaque).
Definition pico_emitter.h:112
void queued_emitter_off_all(queued_emitter_t *qe, int event)
Removes all listeners subscribed to an event.
void emitter_off_all(emitter_t *emitter, int event)
Removes all listeners subscribed to an event.
struct queued_emitter_s queued_emitter_t
Queued event emitter context (opaque).
Definition pico_emitter.h:230
void emitter_off(emitter_t *emitter, int event, emitter_listener_fn listener)
Unsubscribes the first listener whose function pointer matches.
void queued_emitter_once(queued_emitter_t *qe, int event, emitter_listener_fn listener, void *udata)
Subscribes a listener that fires exactly once, then unsubscribes.
void emitter_once(emitter_t *emitter, int event, emitter_listener_fn listener, void *udata)
Subscribes a listener that fires exactly once, then unsubscribes.
int emitter_count(const emitter_t *emitter, int event)
Returns the number of listeners currently subscribed to an event.
emitter_t * emitter_create(int num_events)
Creates an event emitter that supports the given number of event types.
void queued_emitter_flush(queued_emitter_t *qe)
Dispatches all queued events in FIFO order and clears the queue.
bool queued_emitter_resize(queued_emitter_t *qe, int num_events)
Resizes the queued emitter to support a different number of event types.
void emitter_on(emitter_t *emitter, int event, emitter_listener_fn listener, void *udata)
Subscribes a listener to an event.
void emitter_destroy(emitter_t *emitter)
Destroys the emitter and frees all associated memory.
void(* emitter_listener_fn)(const void *data, void *udata)
Listener callback signature.
Definition pico_emitter.h:107
void queued_emitter_on(queued_emitter_t *qe, int event, emitter_listener_fn listener, void *udata)
Subscribes a persistent listener to an event.
queued_emitter_t * queued_emitter_create(int num_events)
Creates a queued emitter supporting the given number of event types.
void queued_emitter_destroy(queued_emitter_t *qe)
Destroys the queued emitter and discards any unflushed events.
void queued_emitter_emit(queued_emitter_t *qe, int event, const void *data)
Emits an event immediately, bypassing the queue.
bool emitter_resize(emitter_t *emitter, int num_events)
Resizes the emitter to support a different number of event types.
void emitter_emit(emitter_t *emitter, int event, const void *data)
Emits an event, invoking all registered listeners in order.