QOF
0.7.5
|
00001 /******************************************************************** 00002 * qofevent.c -- QOF event handling implementation * 00003 * Copyright 2000 Dave Peticolas <dave@krondo.com> * 00004 * Copyright 2006 Neil Williams <linux@codehelp.co.uk> * 00005 * * 00006 * This program is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU General Public License as * 00008 * published by the Free Software Foundation; either version 2 of * 00009 * the License, or (at your option) any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License* 00017 * along with this program; if not, contact: * 00018 * * 00019 * Free Software Foundation Voice: +1-617-542-5942 * 00020 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00021 * Boston, MA 02110-1301, USA gnu@gnu.org * 00022 * * 00023 ********************************************************************/ 00024 00025 #include "config.h" 00026 #include <glib.h> 00027 #include "qof.h" 00028 #include "qofevent-p.h" 00029 00030 /* Static Variables ************************************************/ 00031 static guint suspend_counter = 0; 00032 static gint next_handler_id = 1; 00033 static guint handler_run_level = 0; 00034 static guint pending_deletes = 0; 00035 static GList *handlers = NULL; 00036 00037 /* This static indicates the debugging module that this .o belongs to. */ 00038 static QofLogModule log_module = QOF_MOD_ENGINE; 00039 00040 /* Implementations *************************************************/ 00041 00042 static gint 00043 find_next_handler_id (void) 00044 { 00045 HandlerInfo *hi; 00046 gint handler_id; 00047 GList *node; 00048 00049 /* look for a free handler id */ 00050 handler_id = next_handler_id; 00051 node = handlers; 00052 00053 while (node) 00054 { 00055 hi = node->data; 00056 00057 if (hi->handler_id == handler_id) 00058 { 00059 handler_id++; 00060 node = handlers; 00061 continue; 00062 } 00063 00064 node = node->next; 00065 } 00066 /* Update id for next registration */ 00067 next_handler_id = handler_id + 1; 00068 return handler_id; 00069 } 00070 00071 /* support deprecated code with a private function*/ 00072 #ifndef QOF_DISABLE_DEPRECATED 00073 gint 00074 qof_event_register_old_handler (GNCEngineEventHandler handler, 00075 gpointer user_data) 00076 { 00077 HandlerInfo *hi; 00078 gint handler_id; 00079 00080 ENTER ("(handler=%p, data=%p)", handler, user_data); 00081 00082 /* sanity check */ 00083 if (!handler) 00084 { 00085 PERR ("no handler specified"); 00086 return 0; 00087 } 00088 PINFO (" deprecated handler specified"); 00089 00090 handler_id = find_next_handler_id (); 00091 /* Found one, add the handler */ 00092 hi = g_new0 (HandlerInfo, 1); 00093 00094 hi->old_handler = handler; 00095 hi->user_data = user_data; 00096 hi->handler_id = handler_id; 00097 00098 handlers = g_list_prepend (handlers, hi); 00099 00100 LEAVE (" (handler=%p, data=%p) handler_id=%d", handler, user_data, 00101 handler_id); 00102 return handler_id; 00103 00104 } 00105 #endif /* QOF_DISABLE_DEPRECATED */ 00106 00107 gint 00108 qof_event_register_handler (QofEventHandler handler, gpointer user_data) 00109 { 00110 HandlerInfo *hi; 00111 gint handler_id; 00112 00113 ENTER ("(handler=%p, data=%p)", handler, user_data); 00114 00115 /* sanity check */ 00116 if (!handler) 00117 { 00118 PERR ("no handler specified"); 00119 return 0; 00120 } 00121 00122 /* look for a free handler id */ 00123 handler_id = find_next_handler_id (); 00124 00125 /* Found one, add the handler */ 00126 hi = g_new0 (HandlerInfo, 1); 00127 00128 hi->handler = handler; 00129 hi->user_data = user_data; 00130 hi->handler_id = handler_id; 00131 00132 handlers = g_list_prepend (handlers, hi); 00133 LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, 00134 handler_id); 00135 return handler_id; 00136 } 00137 00138 void 00139 qof_event_unregister_handler (gint handler_id) 00140 { 00141 GList *node; 00142 00143 ENTER ("(handler_id=%d)", handler_id); 00144 for (node = handlers; node; node = node->next) 00145 { 00146 HandlerInfo *hi = node->data; 00147 00148 if (hi->handler_id != handler_id) 00149 continue; 00150 00151 /* Normally, we could actually remove the handler's node from the 00152 list, but we may be unregistering the event handler as a result 00153 of a generated event, such as GNC_EVENT_DESTROY. In that case, 00154 we're in the middle of walking the GList and it is wrong to 00155 modify the list. So, instead, we just NULL the handler. */ 00156 if (hi->handler) 00157 LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id, 00158 hi->handler, hi->user_data); 00159 #ifndef QOF_DISABLE_DEPRECATED 00160 if (hi->old_handler) 00161 LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id, 00162 hi->old_handler, hi->user_data); 00163 #endif 00164 00165 /* safety -- clear the handler in case we're running events now */ 00166 hi->handler = NULL; 00167 #ifndef QOF_DISABLE_DEPRECATED 00168 hi->old_handler = NULL; 00169 #endif 00170 00171 if (handler_run_level == 0) 00172 { 00173 handlers = g_list_remove_link (handlers, node); 00174 g_list_free_1 (node); 00175 g_free (hi); 00176 } 00177 else 00178 { 00179 pending_deletes++; 00180 } 00181 00182 return; 00183 } 00184 00185 PERR ("no such handler: %d", handler_id); 00186 } 00187 00188 void 00189 qof_event_suspend (void) 00190 { 00191 suspend_counter++; 00192 00193 if (suspend_counter == 0) 00194 { 00195 PERR ("suspend counter overflow"); 00196 } 00197 } 00198 00199 void 00200 qof_event_resume (void) 00201 { 00202 if (suspend_counter == 0) 00203 { 00204 PERR ("suspend counter underflow"); 00205 return; 00206 } 00207 00208 suspend_counter--; 00209 } 00210 00211 static void 00212 qof_event_generate_internal (QofEntity * entity, QofEventId event_id, 00213 gpointer event_data) 00214 { 00215 GList *node; 00216 GList *next_node = NULL; 00217 gboolean use_old_handlers = FALSE; 00218 00219 g_return_if_fail (entity); 00220 00221 if (event_id <= QOF_EVENT__LAST) 00222 use_old_handlers = TRUE; 00223 00224 switch (event_id) 00225 { 00226 case QOF_EVENT_NONE: 00227 { 00228 /* if none, don't log, just return. */ 00229 return; 00230 } 00231 } 00232 00233 handler_run_level++; 00234 for (node = handlers; node; node = next_node) 00235 { 00236 HandlerInfo *hi = node->data; 00237 00238 next_node = node->next; 00239 #ifndef QOF_DISABLE_DEPRECATED 00240 if ((hi->old_handler) && (use_old_handlers)) 00241 { 00242 PINFO (" deprecated: id=%d hi=%p han=%p", hi->handler_id, hi, 00243 hi->old_handler); 00244 hi->old_handler ((GUID *) & entity->guid, entity->e_type, 00245 event_id, hi->user_data); 00246 } 00247 #endif 00248 if (hi->handler) 00249 { 00250 PINFO ("id=%d type=%s", hi->handler_id, entity->e_type); 00251 hi->handler (entity, event_id, hi->user_data, event_data); 00252 } 00253 } 00254 handler_run_level--; 00255 00256 /* If we're the outtermost event runner and we have pending deletes 00257 * then go delete the handlers now. 00258 */ 00259 if (handler_run_level == 0 && pending_deletes) 00260 { 00261 for (node = handlers; node; node = next_node) 00262 { 00263 HandlerInfo *hi = node->data; 00264 next_node = node->next; 00265 if ((hi->handler == NULL) 00266 #ifndef QOF_DISABLE_DEPRECATED 00267 && (hi->old_handler == NULL) 00268 #endif 00269 ) 00270 { 00271 /* remove this node from the list, then free this node */ 00272 handlers = g_list_remove_link (handlers, node); 00273 g_list_free_1 (node); 00274 g_free (hi); 00275 } 00276 } 00277 pending_deletes = 0; 00278 } 00279 } 00280 00281 void 00282 qof_event_force (QofEntity * entity, QofEventId event_id, 00283 gpointer event_data) 00284 { 00285 if (!entity) 00286 return; 00287 00288 qof_event_generate_internal (entity, event_id, event_data); 00289 } 00290 00291 void 00292 qof_event_gen (QofEntity * entity, QofEventId event_id, gpointer event_data) 00293 { 00294 if (!entity) 00295 return; 00296 00297 if (suspend_counter) 00298 return; 00299 00300 qof_event_generate_internal (entity, event_id, event_data); 00301 } 00302 00303 /* deprecated */ 00304 void 00305 qof_event_generate (const GUID * guid, QofIdType e_type, QofEventId event_id) 00306 { 00307 QofEntity ent; 00308 ent.guid = *guid; 00309 ent.e_type = e_type; 00310 if (suspend_counter) 00311 return; 00312 /* caution: this is an incomplete entity! */ 00313 qof_event_generate_internal (&ent, event_id, NULL); 00314 } 00315 00316 /* =========================== END OF FILE ======================= */