From eb5e067336c457058b5e67bf5835b778ec100019 Mon Sep 17 00:00:00 2001 From: Richard Kettlewell Date: Sat, 7 Jun 2008 19:53:25 +0100 Subject: [PATCH] General-purpose event distribution interface --- .bzrignore | 1 + lib/Makefile.am | 1 + lib/eventdist.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/eventdist.h | 52 +++++++++++++++++++++++++ libtests/Makefile.am | 3 +- libtests/t-eventdist.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 lib/eventdist.c create mode 100644 lib/eventdist.h create mode 100644 libtests/t-eventdist.c diff --git a/.bzrignore b/.bzrignore index 99a65d9..22ff521 100644 --- a/.bzrignore +++ b/.bzrignore @@ -194,3 +194,4 @@ libtests/t-dateparse libtests/Makefile cgi/Makefile libtests/index.html +libtests/t-eventdist diff --git a/lib/Makefile.am b/lib/Makefile.am index ce28475..2c0d334 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 index 0000000..b2d27d9 --- /dev/null +++ b/lib/eventdist.c @@ -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 index 0000000..a25929c --- /dev/null +++ b/lib/eventdist.h @@ -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: +*/ diff --git a/libtests/Makefile.am b/libtests/Makefile.am index 5c7cc54..c569287 100644 --- a/libtests/Makefile.am +++ b/libtests/Makefile.am @@ -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 index 0000000..1deeb0d --- /dev/null +++ b/libtests/t-eventdist.c @@ -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: +*/ -- 2.11.0