|
Pico Headers
|
A minimal, optimized event emitter written in C99. More...
#include <stdbool.h>#include <stddef.h>
Go to the source code of this file.
Macros | |
| #define | queued_emitter_enqueue(qe, event, ptr) (queued_emitter_enqueue_raw((qe), (event), (ptr), sizeof(*(ptr)))) |
| Convenience macro that enqueues a typed event without an explicit size argument. | |
Typedefs | |
| typedef void(* | emitter_listener_fn) (const void *data, void *udata) |
| Listener callback signature. | |
| typedef struct emitter_s | emitter_t |
| Event emitter context (opaque). | |
| typedef struct queued_emitter_s | queued_emitter_t |
| Queued event emitter context (opaque). | |
Functions | |
| emitter_t * | emitter_create (int num_events) |
| Creates an event emitter that supports the given number of event types. | |
| void | emitter_destroy (emitter_t *emitter) |
| Destroys the emitter and frees all associated memory. | |
| bool | emitter_resize (emitter_t *emitter, int num_events) |
| Resizes the 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_once (emitter_t *emitter, int event, emitter_listener_fn listener, void *udata) |
| Subscribes a listener that fires exactly once, then unsubscribes. | |
| void | emitter_off (emitter_t *emitter, int event, emitter_listener_fn listener) |
| Unsubscribes the first listener whose function pointer matches. | |
| void | emitter_off_all (emitter_t *emitter, int event) |
| Removes all listeners subscribed to an event. | |
| void | emitter_emit (emitter_t *emitter, int event, const void *data) |
| Emits an event, invoking all registered listeners in order. | |
| int | emitter_count (const emitter_t *emitter, int event) |
| Returns the number of listeners currently subscribed 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. | |
| bool | queued_emitter_resize (queued_emitter_t *qe, int num_events) |
| Resizes the queued emitter to support a different number of event types. | |
| void | queued_emitter_on (queued_emitter_t *qe, int event, emitter_listener_fn listener, void *udata) |
| Subscribes a persistent listener to an event. | |
| 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 | queued_emitter_off (queued_emitter_t *qe, int event, emitter_listener_fn listener) |
| Unsubscribes the first listener whose function pointer matches. | |
| void | queued_emitter_off_all (queued_emitter_t *qe, int event) |
| Removes all listeners subscribed to an event. | |
| void | queued_emitter_emit (queued_emitter_t *qe, int event, const void *data) |
| Emits an event immediately, bypassing the queue. | |
| void | queued_emitter_enqueue_raw (queued_emitter_t *qe, int event, const void *data, size_t data_size) |
| Enqueues an event for deferred dispatch. | |
| void | queued_emitter_flush (queued_emitter_t *qe) |
| Dispatches all queued events in FIFO order and clears the queue. | |
| int | queued_emitter_count (const queued_emitter_t *qe, int event) |
| Returns the number of listeners currently subscribed to an event. | |
A minimal, optimized event emitter written in C99.
An event emitter dispatches events to registered listener callbacks. Listeners are associated with an integer event ID in the range [0, num_events). Multiple listeners can be registered per event and are invoked in registration order when the event is emitted.
Listeners may safely call emitter_on, emitter_once, emitter_off, and emitter_off_all from within a callback. Newly registered listeners take effect on the next emit. Removals take effect after the current emit returns.
Define event IDs:
typedef enum { EVT_JUMP, EVT_LAND, EVT_COUNT } my_event_t;
Create an emitter, subscribe, emit, and tear down:
void on_jump(const void* data, void* udata)
{
printf("jumped! value=%d\n", *(int*)data);
}
emitter_t* emitter = emitter_create(EVT_COUNT);
emitter_on(emitter, EVT_JUMP, on_jump, NULL);
int val = 42;
emitter_emit(emitter, EVT_JUMP, &val); // prints "jumped! value=42"
emitter_destroy(emitter);
To use this library in your project, add the following
#define PICO_EMITTER_IMPLEMENTATION #include "pico_emitter.h"
to a source file (once), then simply include the header normally.
| #define queued_emitter_enqueue | ( | qe, | |
| event, | |||
| ptr | |||
| ) | (queued_emitter_enqueue_raw((qe), (event), (ptr), sizeof(*(ptr)))) |
Convenience macro that enqueues a typed event without an explicit size argument.
Equivalent to calling queued_emitter_enqueue_raw with sizeof(*ptr) as the data size. The payload size is deduced at compile time from the pointer's type, so no per-event registration is required.
When ptr is NULL, sizeof(*ptr) is still evaluated at compile time (sizeof does not evaluate its operand), and queued_emitter_enqueue_raw treats a NULL data pointer as no-payload regardless of the size argument, so no copy is performed.
ptr must not be a void*; the compiler cannot apply sizeof to an incomplete type. Use queued_emitter_enqueue_raw directly when the payload is untyped or the size is not derivable from the pointer type.| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| ptr | Typed pointer to the event payload, or NULL for no payload. |
| typedef void(* emitter_listener_fn) (const void *data, void *udata) |
Listener callback signature.
| data | Read-only event payload supplied by the emitter. May be NULL. |
| udata | User data registered alongside the listener. May be NULL. |
| typedef struct emitter_s emitter_t |
Event emitter context (opaque).
| typedef struct queued_emitter_s queued_emitter_t |
Queued event emitter context (opaque).
Wraps an emitter_t and stores events in a buffer instead of dispatching them immediately. Buffered events are dispatched in FIFO order when queued_emitter_flush is called. Subscription functions delegate directly to the underlying emitter.
| emitter_t * emitter_create | ( | int | num_events | ) |
Creates an event emitter that supports the given number of event types.
Event IDs are integers in the range [0, num_events).
| num_events | Positive number of distinct event types. |
| void emitter_destroy | ( | emitter_t * | emitter | ) |
Destroys the emitter and frees all associated memory.
| emitter | The emitter to destroy. Must not be NULL. |
| bool emitter_resize | ( | emitter_t * | emitter, |
| int | num_events | ||
| ) |
Resizes the emitter to support a different number of event types.
The underlying array of per-event listener slots is reallocated to hold num_events entries. When growing, existing listeners are preserved and the newly added event slots start empty. When shrinking, listeners registered on the dropped events are removed and their memory is freed; event IDs must remain in [0, num_events) after the call.
| emitter | The emitter. Must not be NULL. |
| num_events | Positive number of distinct event types. |
| void emitter_on | ( | emitter_t * | emitter, |
| int | event, | ||
| emitter_listener_fn | listener, | ||
| void * | udata | ||
| ) |
Subscribes a listener to an event.
Registering the same listener multiple times results in multiple calls per emit.
| emitter | The emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| listener | Callback to invoke. Must not be NULL. |
| udata | Arbitrary pointer forwarded to the callback. May be NULL. |
| void emitter_once | ( | emitter_t * | emitter, |
| int | event, | ||
| emitter_listener_fn | listener, | ||
| void * | udata | ||
| ) |
Subscribes a listener that fires exactly once, then unsubscribes.
The listener is removed before it is called so that re-registration from within the callback is safe.
| emitter | The emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| listener | Callback to invoke. Must not be NULL. |
| udata | Arbitrary pointer forwarded to the callback. May be NULL. |
| void emitter_off | ( | emitter_t * | emitter, |
| int | event, | ||
| emitter_listener_fn | listener | ||
| ) |
Unsubscribes the first listener whose function pointer matches.
If the same function was registered multiple times, call emitter_off once per registration to remove each occurrence individually.
| emitter | The emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| listener | The function pointer to remove. Must not be NULL. |
| void emitter_off_all | ( | emitter_t * | emitter, |
| int | event | ||
| ) |
Removes all listeners subscribed to an event.
| emitter | The emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| void emitter_emit | ( | emitter_t * | emitter, |
| int | event, | ||
| const void * | data | ||
| ) |
Emits an event, invoking all registered listeners in order.
Listeners added from within a callback are not called in the current emit. Listeners removed from within a callback are not called after removal. Once-listeners are removed before being called.
| emitter | The emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| data | Optional event payload forwarded to each listener. May be NULL. |
| int emitter_count | ( | const emitter_t * | emitter, |
| int | event | ||
| ) |
Returns the number of listeners currently subscribed to an event.
| emitter | The emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| queued_emitter_t * queued_emitter_create | ( | int | num_events | ) |
Creates a queued emitter supporting the given number of event types.
| num_events | Positive number of distinct event types. |
| void queued_emitter_destroy | ( | queued_emitter_t * | qe | ) |
Destroys the queued emitter and discards any unflushed events.
| qe | The queued emitter. Must not be NULL. |
| bool queued_emitter_resize | ( | queued_emitter_t * | qe, |
| int | num_events | ||
| ) |
Resizes the queued emitter to support a different number of event types.
Resizes the wrapped emitter's per-event listener slot array via emitter_resize. Growing preserves existing listeners and leaves the new event slots empty; shrinking removes listeners on the dropped events. Already queued events are unaffected, but any pending event ID must still be in [0, num_events) when queued_emitter_flush runs.
| qe | The queued emitter. Must not be NULL. |
| num_events | Positive number of distinct event types. |
| void queued_emitter_on | ( | queued_emitter_t * | qe, |
| int | event, | ||
| emitter_listener_fn | listener, | ||
| void * | udata | ||
| ) |
Subscribes a persistent listener to an event.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| listener | Callback to invoke. Must not be NULL. |
| udata | Arbitrary pointer forwarded to the callback. May be NULL. |
| 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.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| listener | Callback to invoke. Must not be NULL. |
| udata | Arbitrary pointer forwarded to the callback. May be NULL. |
| void queued_emitter_off | ( | queued_emitter_t * | qe, |
| int | event, | ||
| emitter_listener_fn | listener | ||
| ) |
Unsubscribes the first listener whose function pointer matches.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| listener | The function pointer to remove. Must not be NULL. |
| void queued_emitter_off_all | ( | queued_emitter_t * | qe, |
| int | event | ||
| ) |
Removes all listeners subscribed to an event.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| void queued_emitter_emit | ( | queued_emitter_t * | qe, |
| int | event, | ||
| const void * | data | ||
| ) |
Emits an event immediately, bypassing the queue.
Convenience alias that forwards directly to emitter_emit on the wrapped emitter. Listeners fire synchronously during this call rather than being deferred to the next queued_emitter_flush. Because dispatch is immediate, the payload is not copied; the pointed-to object need only outlive the call.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| data | Optional event payload forwarded to each listener. May be NULL. |
| void queued_emitter_enqueue_raw | ( | queued_emitter_t * | qe, |
| int | event, | ||
| const void * | data, | ||
| size_t | data_size | ||
| ) |
Enqueues an event for deferred dispatch.
If data is non-NULL and data_size is greater than zero, the payload is copied into the emitter's internal arena. The caller does not need to keep the pointed-to object alive after this call returns.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |
| data | Optional event payload. May be NULL. |
| data_size | Size in bytes of the object pointed to by data. Pass 0 when data is NULL or when a pointer-only reference is intentionally stored without copying. |
| void queued_emitter_flush | ( | queued_emitter_t * | qe | ) |
Dispatches all queued events in FIFO order and clears the queue.
Events enqueued by listeners during flush are deferred to the next call.
| qe | The queued emitter. Must not be NULL. |
| int queued_emitter_count | ( | const queued_emitter_t * | qe, |
| int | event | ||
| ) |
Returns the number of listeners currently subscribed to an event.
| qe | The queued emitter. Must not be NULL. |
| event | Event ID in [0, num_events). |