chiark / gitweb /
General-purpose event distribution interface
authorRichard Kettlewell <rjk@greenend.org.uk>
Sat, 7 Jun 2008 18:53:25 +0000 (19:53 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sat, 7 Jun 2008 18:53:25 +0000 (19:53 +0100)
.bzrignore
lib/Makefile.am
lib/eventdist.c [new file with mode: 0644]
lib/eventdist.h [new file with mode: 0644]
libtests/Makefile.am
libtests/t-eventdist.c [new file with mode: 0644]

index 99a65d9..22ff521 100644 (file)
@@ -194,3 +194,4 @@ libtests/t-dateparse
 libtests/Makefile
 cgi/Makefile
 libtests/index.html
+libtests/t-eventdist
index ce28475..2c0d334 100644 (file)
@@ -44,6 +44,7 @@ libdisorder_a_SOURCES=charset.c charset.h             \
        dateparse.c dateparse.h xgetdate.c              \
        defs.c defs.h                                   \
        eclient.c eclient.h                             \
+       eventdist.c eventdist.h                         \
        event.c event.h                                 \
        eventlog.c eventlog.h                           \
        filepart.c filepart.h                           \
diff --git a/lib/eventdist.c b/lib/eventdist.c
new file mode 100644 (file)
index 0000000..b2d27d9
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This file is part of DisOrder
+ * Copyright (C) 2008 Richard Kettlewell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "common.h"
+
+#include "mem.h"
+#include "eventdist.h"
+#include "hash.h"
+
+struct event_data {
+  struct event_data *next;
+  const char *event;
+  event_handler *callback;
+  void *callbackdata;
+};
+
+static hash *events;
+
+/** @brief Register an event handler
+ * @param event Event type to handle
+ * @param callback Function to call when event occurs
+ * @param callbackdata Passed to @p callback
+ * @return Handle for this registration (for use with event_cancel())
+ */
+event_handle event_register(const char *event,
+                            event_handler *callback,
+                            void *callbackdata) {
+  static const struct event_data *null;
+  struct event_data *ed = xmalloc(sizeof *ed), **head;
+
+  if(!events)
+    events = hash_new(sizeof (struct event_data *));
+  if(!(head = hash_find(events, event))) {
+    hash_add(events, event, &null, HASH_INSERT);
+    head = hash_find(events, event);
+  }
+  ed->next = *head;
+  ed->event = xstrdup(event);
+  ed->callback = callback;
+  ed->callbackdata = callbackdata;
+  *head = ed;
+  return ed;
+}
+
+/** @brief Stop handling an event
+ * @param handle Registration to cancel (as returned from event_register())
+ *
+ * @p handle is allowed to be NULL.
+ */
+void event_cancel(event_handle handle) {
+  struct event_data **head, **edp;
+  
+  if(!handle)
+    return;
+  assert(events);
+  head = hash_find(events, handle->event);
+  for(edp = head; *edp && *edp != handle; edp = &(*edp)->next)
+    ;
+  assert(*edp == handle);
+  *edp = handle->next;
+}
+
+/** @brief Raise an event
+ * @param event Event type to raise
+ * @param eventdata Event-specific data
+ */
+void event_raise(const char *event,
+                 void *eventdata) {
+  struct event_data *ed, **head;
+  if(!events)
+    return;
+  if(!(head = hash_find(events, event)))
+    return;
+  for(ed = *head; ed; ed = ed->next)
+    ed->callback(event, eventdata, ed->callbackdata);
+}
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/
diff --git a/lib/eventdist.h b/lib/eventdist.h
new file mode 100644 (file)
index 0000000..a25929c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file is part of DisOrder
+ * Copyright (C) 2008 Richard Kettlewell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef EVENTDIST_H
+#define EVENTDIST_H
+
+/** @brief Signature for event handlers
+ * @param event Event type
+ * @param eventdata Event-specific data
+ * @param callbackdata Handler-specific data (as passed to event_register())
+ */
+typedef void event_handler(const char *event,
+                           void *eventdata,
+                           void *callbackdata);
+
+/** @brief Handle identifying an event monitor */
+typedef struct event_data *event_handle;
+
+event_handle event_register(const char *event,
+                            event_handler *callback,
+                            void *callbackdata);
+void event_cancel(event_handle handle);
+void event_raise(const char *event,
+                 void *eventdata);
+
+#endif /* EVENTDIST_H */
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/
index 5c7cc54..c569287 100644 (file)
@@ -22,7 +22,7 @@ TESTS=t-addr t-arcfour t-basen t-bits t-cache t-casefold t-charset    \
        t-cookies t-dateparse t-event t-filepart t-hash t-heap t-hex    \
        t-kvp t-mime t-printf t-regsub t-selection t-signame t-sink     \
        t-split t-syscalls t-trackname t-unicode t-url t-utf8 t-vector  \
-       t-words t-wstat t-macros t-cgi
+       t-words t-wstat t-macros t-cgi t-eventdist
 
 noinst_PROGRAMS=$(TESTS)
 
@@ -61,6 +61,7 @@ t_utf8_SOURCES=t-utf8.c test.c test.h
 t_vector_SOURCES=t-vector.c test.c test.h
 t_words_SOURCES=t-words.c test.c test.h
 t_wstat_SOURCES=t-wstat.c test.c test.h
+t_eventdist_SOURCES=t-eventdist.c test.c test.h
 
 check-report: before-check check make-coverage-reports
 before-check:
diff --git a/libtests/t-eventdist.c b/libtests/t-eventdist.c
new file mode 100644 (file)
index 0000000..1deeb0d
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * This file is part of DisOrder.
+ * Copyright (C) 2008 Richard Kettlewell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#include "test.h"
+#include "eventdist.h"
+
+static int wibbles, wobbles, wobble2s;
+
+static void on_wibble(const char *event, void *eventdata, void *callbackdata) {
+  check_string(event, "wibble");
+  check_string(eventdata, "wibble_eventdata");
+  check_string(callbackdata, "wibble_data");
+  ++wibbles;
+}
+
+static void on_wobble(const char *event, void *eventdata, void *callbackdata) {
+  check_string(event, "wobble");
+  check_string(eventdata, "wobble_eventdata");
+  check_string(callbackdata, "wobble_data");
+  ++wobbles;
+}
+
+static void on_wobble2(const char *event, void *eventdata, void *callbackdata) {
+  check_string(event, "wobble");
+  check_string(eventdata, "wobble_eventdata");
+  check_string(callbackdata, "wobble2_data");
+  ++wobble2s;
+}
+
+static void test_eventdist(void) {
+  event_handle wibble_handle, wobble_handle, wobble2_handle;
+  /* Raising unregistered events should be safe */
+  event_raise("wibble", NULL);
+  ++tests;
+  
+  wibble_handle = event_register("wibble", on_wibble, (void *)"wibble_data");
+  wobble_handle = event_register("wobble", on_wobble, (void *)"wobble_data");
+  wobble2_handle = event_register("wobble", on_wobble2, (void *)"wobble2_data");
+  event_raise("wibble", (void *) "wibble_eventdata");
+  check_integer(wibbles, 1);
+  check_integer(wobbles, 0);
+  check_integer(wobble2s, 0);
+
+  event_raise("wobble", (void *)"wobble_eventdata");
+  check_integer(wibbles, 1);
+  check_integer(wobbles, 1);
+  check_integer(wobble2s, 1);
+
+  event_raise("wobble", (void *)"wobble_eventdata");
+  check_integer(wibbles, 1);
+  check_integer(wobbles, 2);
+  check_integer(wobble2s, 2);
+
+  event_cancel(wobble_handle);
+  
+  event_raise("wibble", (void *)"wibble_eventdata");
+  check_integer(wibbles, 2);
+  check_integer(wobbles, 2);
+  check_integer(wobble2s, 2);
+  
+  event_raise("wobble", (void *)"wobble_eventdata");
+  check_integer(wibbles, 2);
+  check_integer(wobbles, 2);
+  check_integer(wobble2s, 3);
+}
+
+TEST(eventdist);
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/