diff options
-rw-r--r-- | src/afb-evt.c | 92 |
1 files changed, 88 insertions, 4 deletions
diff --git a/src/afb-evt.c b/src/afb-evt.c index ad5695f1..a99dc894 100644 --- a/src/afb-evt.c +++ b/src/afb-evt.c @@ -28,46 +28,89 @@ #include "afb-evt.h" - struct afb_evt_watch; +/* + * Structure for event listeners + */ struct afb_evt_listener { + + /* chaining listeners */ struct afb_evt_listener *next; + + /* callback on event */ void (*send)(void *closure, const char *event, struct json_object *object); + + /* closure for the callback */ void *closure; + + /* head of the list of events listened */ struct afb_evt_watch *watchs; + + /* count of reference to the listener */ int refcount; }; +/* + * Structure for describing events + */ struct afb_evt_event { + + /* head of the list of listeners watching the event */ struct afb_evt_watch *watchs; + + /* name of the event */ char name[1]; }; +/* + * Structure for associating events and listeners + */ struct afb_evt_watch { + + /* the event */ struct afb_evt_event *event; + + /* link to the next listener for the same event */ struct afb_evt_watch *next_by_event; + + /* the listener */ struct afb_evt_listener *listener; + + /* link to the next event for the same listener */ struct afb_evt_watch *next_by_listener; }; +/* declare functions */ static int evt_broadcast(struct afb_evt_event *evt, struct json_object *obj); static int evt_push(struct afb_evt_event *evt, struct json_object *obj); -static void evt_drop(struct afb_evt_event *evt); +static void evt_destroy(struct afb_evt_event *evt); +/* the interface for events */ static struct afb_event_itf afb_evt_event_itf = { .broadcast = (void*)evt_broadcast, .push = (void*)evt_push, - .drop = (void*)evt_drop + .drop = (void*)evt_destroy }; +/* head of the list of listeners */ static struct afb_evt_listener *listeners = NULL; +/* + * Broadcasts the event 'evt' with its 'object' + * 'object' is released (like json_object_put) + * Returns the count of listener that received the event. + */ static int evt_broadcast(struct afb_evt_event *evt, struct json_object *object) { return afb_evt_broadcast(evt->name, object); } +/* + * Broadcasts the 'event' with its 'object' + * 'object' is released (like json_object_put) + * Returns the count of listener having receive the event. + */ int afb_evt_broadcast(const char *event, struct json_object *object) { int result; @@ -78,11 +121,17 @@ int afb_evt_broadcast(const char *event, struct json_object *object) while(listener) { listener->send(listener->closure, event, json_object_get(object)); listener = listener->next; + result++; } json_object_put(object); return result; } +/* + * Broadcasts the event 'evt' with its 'object' + * 'object' is released (like json_object_put) + * Returns the count of listener taht received the event. + */ static int evt_push(struct afb_evt_event *evt, struct json_object *obj) { int result; @@ -95,37 +144,52 @@ static int evt_push(struct afb_evt_event *evt, struct json_object *obj) listener = watch->listener; listener->send(listener->closure, evt->name, json_object_get(obj)); watch = watch->next_by_event; + result++; } json_object_put(obj); return result; } +/* + * remove the 'watch' + */ static void remove_watch(struct afb_evt_watch *watch) { struct afb_evt_watch **prv; + /* unlink the watch for its event */ prv = &watch->event->watchs; while(*prv != watch) prv = &(*prv)->next_by_event; *prv = watch->next_by_event; + /* unlink the watch for its listener */ prv = &watch->listener->watchs; while(*prv != watch) prv = &(*prv)->next_by_listener; *prv = watch->next_by_listener; + /* recycle memory */ free(watch); } -static void evt_drop(struct afb_evt_event *evt) +/* + * Destroys the event 'evt' + */ +static void evt_destroy(struct afb_evt_event *evt) { if (evt != NULL) { + /* removes all watchers */ while(evt->watchs != NULL) remove_watch(evt->watchs); free(evt); } } +/* + * Creates an event of 'name' and returns it. + * Returns an event with closure==NULL in case of error. + */ struct afb_event afb_evt_create_event(const char *name) { size_t len; @@ -140,6 +204,11 @@ struct afb_event afb_evt_create_event(const char *name) return (struct afb_event){ .itf = &afb_evt_event_itf, .closure = evt }; } +/* + * Returns an instance of the listener defined by the 'send' callback + * and the 'closure'. + * Returns NULL in case of memory depletion. + */ struct afb_evt_listener *afb_evt_listener_create(void (*send)(void *closure, const char *event, struct json_object *object), void *closure) { struct afb_evt_listener *listener; @@ -166,12 +235,19 @@ struct afb_evt_listener *afb_evt_listener_create(void (*send)(void *closure, con return listener; } +/* + * Increases the reference count of 'listener' and returns it + */ struct afb_evt_listener *afb_evt_listener_addref(struct afb_evt_listener *listener) { listener->refcount++; return listener; } +/* + * Decreases the reference count of the 'listener' and destroys it + * when no more used. + */ void afb_evt_listener_unref(struct afb_evt_listener *listener) { if (0 == --listener->refcount) { @@ -192,6 +268,10 @@ void afb_evt_listener_unref(struct afb_evt_listener *listener) } } +/* + * Makes the 'listener' watching 'event' + * Returns 0 in case of success or else -1. + */ int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event) { struct afb_evt_watch *watch; @@ -230,6 +310,10 @@ int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event) return 0; } +/* + * Avoids the 'listener' to watch 'event' + * Returns 0 in case of success or else -1. + */ int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event event) { struct afb_evt_watch *watch; |