chiark / gitweb /
socketio sink
[disorder] / lib / eventdist.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2008 Richard Kettlewell
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file lib/eventdist.c
19  * @brief Event distribution
20  */
21 #include "common.h"
22
23 #include "mem.h"
24 #include "eventdist.h"
25 #include "hash.h"
26
27 /** @brief Event data
28  *
29  * @c event_data structures form linked lists; one list per event and one node
30  * per handler.
31  */
32 struct event_data {
33   /** @brief Next handler */
34   struct event_data *next;
35
36   /** @brief Name of event */
37   const char *event;
38
39   /** @brief Handler callback */
40   event_handler *callback;
41
42   /** @brief Passed to @ref callback */
43   void *callbackdata;
44 };
45
46 static hash *events;
47
48 /** @brief Register an event handler
49  * @param event Event type to handle
50  * @param callback Function to call when event occurs
51  * @param callbackdata Passed to @p callback
52  * @return Handle for this registration (for use with event_cancel())
53  */
54 event_handle event_register(const char *event,
55                             event_handler *callback,
56                             void *callbackdata) {
57   static const struct event_data *null;
58   struct event_data *ed = xmalloc(sizeof *ed), **head;
59
60   if(!events)
61     events = hash_new(sizeof (struct event_data *));
62   if(!(head = hash_find(events, event))) {
63     hash_add(events, event, &null, HASH_INSERT);
64     head = hash_find(events, event);
65   }
66   ed->next = *head;
67   ed->event = xstrdup(event);
68   ed->callback = callback;
69   ed->callbackdata = callbackdata;
70   *head = ed;
71   return ed;
72 }
73
74 /** @brief Stop handling an event
75  * @param handle Registration to cancel (as returned from event_register())
76  *
77  * @p handle is allowed to be NULL.
78  */
79 void event_cancel(event_handle handle) {
80   struct event_data **head, **edp;
81   
82   if(!handle)
83     return;
84   assert(events);
85   head = hash_find(events, handle->event);
86   for(edp = head; *edp && *edp != handle; edp = &(*edp)->next)
87     ;
88   assert(*edp == handle);
89   *edp = handle->next;
90 }
91
92 /** @brief Raise an event
93  * @param event Event type to raise
94  * @param eventdata Event-specific data
95  */
96 void event_raise(const char *event,
97                  void *eventdata) {
98   struct event_data *ed, **head;
99   if(!events)
100     return;
101   if(!(head = hash_find(events, event)))
102     return;
103   for(ed = *head; ed; ed = ed->next)
104     ed->callback(event, eventdata, ed->callbackdata);
105 }
106
107 /*
108 Local Variables:
109 c-basic-offset:2
110 comment-column:40
111 fill-column:79
112 indent-tabs-mode:nil
113 End:
114 */