summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/afb-evt.c92
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;