Last active
April 27, 2017 20:13
-
-
Save FergusInLondon/761e675950ee37e80645b50d67ed2aec to your computer and use it in GitHub Desktop.
Really simple events/listeners registry in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Simple little event registry built around the worlds most simplistic | |
* linked list implementation. Allows you to register a function (void()) | |
* against a integer value, and provides a mechanism for triggering the | |
* associated functions for an integer. | |
* | |
* Not a great deal of use beyond those fun little weekend Arduino type | |
* projects. | |
* | |
* @see example.c | |
*/ | |
#include <stdlib.h> | |
#include <stdint.h> | |
/* Our Callback Type; simple function that accepts no parameters and provides | |
no return. Could possibly expand upon this so that it takes some form of | |
callback_parameter_t struct, which holds event data.. but we're making this | |
as generic as possible. */ | |
typedef void(*evt_callback_t)(); | |
/* Listener Struct; this is essentially a Linked List entry which additionally | |
contains a numerical identifier for an event, and a callback_t for the | |
listener */ | |
typedef struct listener_entry { | |
struct listener_entry *next; | |
struct listener_entry *prev; | |
uint8_t ident; | |
evt_callback_t callback; | |
} evt_listener_t; | |
/* Pointers for referencing the beginning and end elements of our list */ | |
typedef struct listener_registry { | |
evt_listener_t *base; | |
evt_listener_t *tail; | |
} evt_listener_registry_t; | |
/** | |
* Create a new registry to store our events and callbacks. | |
*/ | |
evt_listener_registry_t *evt_create_registry() { | |
evt_listener_registry_t *registry = malloc(sizeof(evt_listener_registry_t)); | |
registry->base = NULL; | |
registry->tail = NULL; | |
return registry; | |
} | |
/** | |
* Triggers an event, accepts the numerical identifier of the event before | |
* iterating through our Linked List and finding relevant listener callbacks. | |
*/ | |
void evt_trigger(evt_listener_registry_t *registry, uint8_t ident) { | |
if (registry->base == NULL) return; | |
evt_listener_t *cursor = registry->base; | |
do { | |
if (cursor->ident == ident) cursor->callback(); | |
} while ((cursor = cursor->next) != NULL); | |
} | |
/** | |
* Registers a new listener, accepts a numerical event identifier and a callback_t | |
* listener, and appends it to the Linked List. | |
*/ | |
evt_listener_t *evt_register_listener(evt_listener_registry_t *registry, uint8_t event, evt_callback_t cb) { | |
evt_listener_t *entry = malloc(sizeof(evt_listener_t)); | |
entry->callback = cb; | |
entry->ident = event; | |
if (registry->base == NULL){ | |
registry->base = entry; | |
} else { | |
entry->prev = registry->tail; | |
registry->tail->next = entry; | |
} | |
registry->tail = entry; | |
return registry->tail; | |
} | |
/** | |
* Removes a listener callback from the Linked List. | |
*/ | |
void evt_remove_listener(evt_listener_registry_t *registry, evt_listener_t *listener) { | |
if (listener == registry->base) { | |
registry->base = listener->next; | |
registry->base->prev = NULL; | |
} else if(listener == registry->tail) { | |
registry->tail->prev->next = NULL; | |
registry->tail = registry->tail->prev; | |
} else { | |
listener->prev->next = listener->next; | |
listener->prev->next->prev = listener->prev; | |
} | |
free(listener); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example Usage