QOF: qofevent.c Source File

QOF 0.7.5

qofevent.c
1 /********************************************************************
2 * qofevent.c -- QOF event handling implementation *
3 * Copyright 2000 Dave Peticolas <dave@krondo.com> *
4 * Copyright 2006 Neil Williams <linux@codehelp.co.uk> *
5 * *
6 * This program is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU General Public License as *
8 * published by the Free Software Foundation; either version 2 of *
9 * the License, or (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License*
17 * along with this program; if not, contact: *
18 * *
19 * Free Software Foundation Voice: +1-617-542-5942 *
20 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 * Boston, MA 02110-1301, USA gnu@gnu.org *
22 * *
23 ********************************************************************/
24
25 #include "config.h"
26 #include <glib.h>
27 #include "qof.h"
28 #include "qofevent-p.h"
29
30 /* Static Variables ************************************************/
31 static guint suspend_counter = 0;
32 static gint next_handler_id = 1;
33 static guint handler_run_level = 0;
34 static guint pending_deletes = 0;
35 static GList *handlers = NULL;
36
37 /* This static indicates the debugging module that this .o belongs to. */
38 static QofLogModule log_module = QOF_MOD_ENGINE;
39
40 /* Implementations *************************************************/
41
42 static gint
43 find_next_handler_id (void)
44 {
45 HandlerInfo *hi;
46 gint handler_id;
47 GList *node;
48
49 /* look for a free handler id */
50 handler_id = next_handler_id;
51 node = handlers;
52
53 while (node)
54 {
55 hi = node->data;
56
57 if (hi->handler_id == handler_id)
58 {
59 handler_id++;
60 node = handlers;
61 continue;
62 }
63
64 node = node->next;
65 }
66 /* Update id for next registration */
67 next_handler_id = handler_id + 1;
68 return handler_id;
69 }
70
71 /* support deprecated code with a private function*/
72 #ifndef QOF_DISABLE_DEPRECATED
73 gint
74 qof_event_register_old_handler (GNCEngineEventHandler handler,
75 gpointer user_data)
76 {
77 HandlerInfo *hi;
78 gint handler_id;
79
80 ENTER ("(handler=%p, data=%p)", handler, user_data);
81
82 /* sanity check */
83 if (!handler)
84 {
85 PERR ("no handler specified");
86 return 0;
87 }
88 PINFO (" deprecated handler specified");
89
90 handler_id = find_next_handler_id ();
91 /* Found one, add the handler */
92 hi = g_new0 (HandlerInfo, 1);
93
94 hi->old_handler = handler;
95 hi->user_data = user_data;
96 hi->handler_id = handler_id;
97
98 handlers = g_list_prepend (handlers, hi);
99
100 LEAVE (" (handler=%p, data=%p) handler_id=%d", handler, user_data,
101 handler_id);
102 return handler_id;
103
104 }
105 #endif /* QOF_DISABLE_DEPRECATED */
106
107 gint
108 qof_event_register_handler (QofEventHandler handler, gpointer user_data)
109 {
110 HandlerInfo *hi;
111 gint handler_id;
112
113 ENTER ("(handler=%p, data=%p)", handler, user_data);
114
115 /* sanity check */
116 if (!handler)
117 {
118 PERR ("no handler specified");
119 return 0;
120 }
121
122 /* look for a free handler id */
123 handler_id = find_next_handler_id ();
124
125 /* Found one, add the handler */
126 hi = g_new0 (HandlerInfo, 1);
127
128 hi->handler = handler;
129 hi->user_data = user_data;
130 hi->handler_id = handler_id;
131
132 handlers = g_list_prepend (handlers, hi);
133 LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data,
134 handler_id);
135 return handler_id;
136 }
137
138 void
139 qof_event_unregister_handler (gint handler_id)
140 {
141 GList *node;
142
143 ENTER ("(handler_id=%d)", handler_id);
144 for (node = handlers; node; node = node->next)
145 {
146 HandlerInfo *hi = node->data;
147
148 if (hi->handler_id != handler_id)
149 continue;
150
151 /* Normally, we could actually remove the handler's node from the
152 list, but we may be unregistering the event handler as a result
153 of a generated event, such as GNC_EVENT_DESTROY. In that case,
154 we're in the middle of walking the GList and it is wrong to
155 modify the list. So, instead, we just NULL the handler. */
156 if (hi->handler)
157 LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
158 hi->handler, hi->user_data);
159 #ifndef QOF_DISABLE_DEPRECATED
160 if (hi->old_handler)
161 LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
162 hi->old_handler, hi->user_data);
163 #endif
164
165 /* safety -- clear the handler in case we're running events now */
166 hi->handler = NULL;
167 #ifndef QOF_DISABLE_DEPRECATED
168 hi->old_handler = NULL;
169 #endif
170
171 if (handler_run_level == 0)
172 {
173 handlers = g_list_remove_link (handlers, node);
174 g_list_free_1 (node);
175 g_free (hi);
176 }
177 else
178 {
179 pending_deletes++;
180 }
181
182 return;
183 }
184
185 PERR ("no such handler: %d", handler_id);
186 }
187
188 void
189 qof_event_suspend (void)
190 {
191 suspend_counter++;
192
193 if (suspend_counter == 0)
194 {
195 PERR ("suspend counter overflow");
196 }
197 }
198
199 void
200 qof_event_resume (void)
201 {
202 if (suspend_counter == 0)
203 {
204 PERR ("suspend counter underflow");
205 return;
206 }
207
208 suspend_counter--;
209 }
210
211 static void
212 qof_event_generate_internal (QofEntity * entity, QofEventId event_id,
213 gpointer event_data)
214 {
215 GList *node;
216 GList *next_node = NULL;
217 gboolean use_old_handlers = FALSE;
218
219 g_return_if_fail (entity);
220
221 if (event_id <= QOF_EVENT__LAST)
222 use_old_handlers = TRUE;
223
224 switch (event_id)
225 {
226 case QOF_EVENT_NONE:
227 {
228 /* if none, don't log, just return. */
229 return;
230 }
231 }
232
233 handler_run_level++;
234 for (node = handlers; node; node = next_node)
235 {
236 HandlerInfo *hi = node->data;
237
238 next_node = node->next;
239 #ifndef QOF_DISABLE_DEPRECATED
240 if ((hi->old_handler) && (use_old_handlers))
241 {
242 PINFO (" deprecated: id=%d hi=%p han=%p", hi->handler_id, hi,
243 hi->old_handler);
244 hi->old_handler ((GUID *) & entity->guid, entity->e_type,
245 event_id, hi->user_data);
246 }
247 #endif
248 if (hi->handler)
249 {
250 PINFO ("id=%d type=%s", hi->handler_id, entity->e_type);
251 hi->handler (entity, event_id, hi->user_data, event_data);
252 }
253 }
254 handler_run_level--;
255
256 /* If we're the outtermost event runner and we have pending deletes
257 * then go delete the handlers now.
258 */
259 if (handler_run_level == 0 && pending_deletes)
260 {
261 for (node = handlers; node; node = next_node)
262 {
263 HandlerInfo *hi = node->data;
264 next_node = node->next;
265 if ((hi->handler == NULL)
266 #ifndef QOF_DISABLE_DEPRECATED
267 && (hi->old_handler == NULL)
268 #endif
269 )
270 {
271 /* remove this node from the list, then free this node */
272 handlers = g_list_remove_link (handlers, node);
273 g_list_free_1 (node);
274 g_free (hi);
275 }
276 }
277 pending_deletes = 0;
278 }
279 }
280
281 void
282 qof_event_force (QofEntity * entity, QofEventId event_id,
283 gpointer event_data)
284 {
285 if (!entity)
286 return;
287
288 qof_event_generate_internal (entity, event_id, event_data);
289 }
290
291 void
292 qof_event_gen (QofEntity * entity, QofEventId event_id, gpointer event_data)
293 {
294 if (!entity)
295 return;
296
297 if (suspend_counter)
298 return;
299
300 qof_event_generate_internal (entity, event_id, event_data);
301 }
302
303 /* deprecated */
304 void
305 qof_event_generate (const GUID * guid, QofIdType e_type, QofEventId event_id)
306 {
307 QofEntity ent;
308 ent.guid = *guid;
309 ent.e_type = e_type;
310 if (suspend_counter)
311 return;
312 /* caution: this is an incomplete entity! */
313 qof_event_generate_internal (&ent, event_id, NULL);
314 }
315
316 /* =========================== END OF FILE ======================= */
PERR
#define PERR(format, args...)
Definition: qoflog.h:183
qof_event_register_old_handler
gint qof_event_register_old_handler(GNCEngineEventHandler old_handler, gpointer user_data)
Definition: qofevent.c:74
QofIdType
const gchar * QofIdType
Definition: qofid.h:81
PINFO
#define PINFO(format, args...)
Definition: qoflog.h:199
QofEntity_s
Definition: qofid.h:147
QofEventHandler
void(* QofEventHandler)(QofEntity *ent, QofEventId event_type, gpointer handler_data, gpointer event_data)
Handler invoked when an event is generated.
Definition: qofevent.h:104
HandlerInfo
Definition: qofevent-p.h:31
LEAVE
#define LEAVE(format, args...)
Definition: qoflog.h:227
GNCEngineEventHandler
void(* GNCEngineEventHandler)(GUID *entity, QofIdType type, QofEventId event_type, gpointer user_data)
Definition: deprecated.h:110
qof_event_gen
void qof_event_gen(QofEntity *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.c:292
HandlerInfo::handler
QofEventHandler handler
Definition: qofevent-p.h:36
qof_event_register_handler
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Definition: qofevent.c:108
QofEventId
gint QofEventId
Definition: qofevent.h:40
qof_event_unregister_handler
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
Definition: qofevent.c:139
QOF_EVENT_NONE
#define QOF_EVENT_NONE
Definition: qofevent.h:69
_GUID
Definition: guid.h:53
qof_event_suspend
void qof_event_suspend(void)
Suspend all engine events.
Definition: qofevent.c:189
qof_event_resume
void qof_event_resume(void)
Definition: qofevent.c:200
ENTER
#define ENTER(format, args...)
Definition: qoflog.h:217
QofLogModule
const gchar * QofLogModule
Definition: qofid.h:85