Pico Headers
Loading...
Searching...
No Matches
Macros | Typedefs | Functions
pico_emitter.h File Reference

A minimal, optimized event emitter written in C99. More...

#include <stdbool.h>
#include <stddef.h>
Include dependency graph for pico_emitter.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_temitter_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_tqueued_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.
 

Detailed Description

A minimal, optimized event emitter written in C99.


Licensing information at end of header

Features:

Summary:

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.

Example:

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);

Revision History:

Usage:

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.

Macros:

Macro Definition Documentation

◆ queued_emitter_enqueue

#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.

Note
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.
Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
ptrTyped pointer to the event payload, or NULL for no payload.

Typedef Documentation

◆ emitter_listener_fn

typedef void(* emitter_listener_fn) (const void *data, void *udata)

Listener callback signature.

Parameters
dataRead-only event payload supplied by the emitter. May be NULL.
udataUser data registered alongside the listener. May be NULL.

◆ emitter_t

typedef struct emitter_s emitter_t

Event emitter context (opaque).

◆ queued_emitter_t

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.

Function Documentation

◆ emitter_create()

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).

Parameters
num_eventsPositive number of distinct event types.
Returns
A pointer to the new emitter, or NULL if allocation failed.

◆ emitter_destroy()

void emitter_destroy ( emitter_t emitter)

Destroys the emitter and frees all associated memory.

Parameters
emitterThe emitter to destroy. Must not be NULL.

◆ emitter_resize()

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.

Parameters
emitterThe emitter. Must not be NULL.
num_eventsPositive number of distinct event types.
Returns
true on success, or false if reallocation failed (in which case the emitter is left unchanged).

◆ emitter_on()

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.

Parameters
emitterThe emitter. Must not be NULL.
eventEvent ID in [0, num_events).
listenerCallback to invoke. Must not be NULL.
udataArbitrary pointer forwarded to the callback. May be NULL.

◆ emitter_once()

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.

Parameters
emitterThe emitter. Must not be NULL.
eventEvent ID in [0, num_events).
listenerCallback to invoke. Must not be NULL.
udataArbitrary pointer forwarded to the callback. May be NULL.

◆ emitter_off()

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.

Parameters
emitterThe emitter. Must not be NULL.
eventEvent ID in [0, num_events).
listenerThe function pointer to remove. Must not be NULL.

◆ emitter_off_all()

void emitter_off_all ( emitter_t emitter,
int  event 
)

Removes all listeners subscribed to an event.

Parameters
emitterThe emitter. Must not be NULL.
eventEvent ID in [0, num_events).

◆ emitter_emit()

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.

Parameters
emitterThe emitter. Must not be NULL.
eventEvent ID in [0, num_events).
dataOptional event payload forwarded to each listener. May be NULL.

◆ emitter_count()

int emitter_count ( const emitter_t emitter,
int  event 
)

Returns the number of listeners currently subscribed to an event.

Parameters
emitterThe emitter. Must not be NULL.
eventEvent ID in [0, num_events).
Returns
The listener count for the given event.

◆ queued_emitter_create()

queued_emitter_t * queued_emitter_create ( int  num_events)

Creates a queued emitter supporting the given number of event types.

Parameters
num_eventsPositive number of distinct event types.
Returns
A pointer to the new queued emitter, or NULL if allocation failed.

◆ queued_emitter_destroy()

void queued_emitter_destroy ( queued_emitter_t qe)

Destroys the queued emitter and discards any unflushed events.

Parameters
qeThe queued emitter. Must not be NULL.

◆ queued_emitter_resize()

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.

Parameters
qeThe queued emitter. Must not be NULL.
num_eventsPositive number of distinct event types.
Returns
true on success, or false if reallocation failed (in which case the queued emitter is left unchanged).

◆ queued_emitter_on()

void queued_emitter_on ( queued_emitter_t qe,
int  event,
emitter_listener_fn  listener,
void *  udata 
)

Subscribes a persistent listener to an event.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
listenerCallback to invoke. Must not be NULL.
udataArbitrary pointer forwarded to the callback. May be NULL.

◆ queued_emitter_once()

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.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
listenerCallback to invoke. Must not be NULL.
udataArbitrary pointer forwarded to the callback. May be NULL.

◆ queued_emitter_off()

void queued_emitter_off ( queued_emitter_t qe,
int  event,
emitter_listener_fn  listener 
)

Unsubscribes the first listener whose function pointer matches.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
listenerThe function pointer to remove. Must not be NULL.

◆ queued_emitter_off_all()

void queued_emitter_off_all ( queued_emitter_t qe,
int  event 
)

Removes all listeners subscribed to an event.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).

◆ queued_emitter_emit()

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.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
dataOptional event payload forwarded to each listener. May be NULL.

◆ queued_emitter_enqueue_raw()

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.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
dataOptional event payload. May be NULL.
data_sizeSize 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.

◆ queued_emitter_flush()

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.

Parameters
qeThe queued emitter. Must not be NULL.

◆ queued_emitter_count()

int queued_emitter_count ( const queued_emitter_t qe,
int  event 
)

Returns the number of listeners currently subscribed to an event.

Parameters
qeThe queued emitter. Must not be NULL.
eventEvent ID in [0, num_events).
Returns
The listener count for the given event.