|
GnuCash 2.4.99
|
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 gint 00072 qof_event_register_handler (QofEventHandler handler, gpointer user_data) 00073 { 00074 HandlerInfo *hi; 00075 gint handler_id; 00076 00077 ENTER ("(handler=%p, data=%p)", handler, user_data); 00078 00079 /* sanity check */ 00080 if (!handler) 00081 { 00082 PERR ("no handler specified"); 00083 return 0; 00084 } 00085 00086 /* look for a free handler id */ 00087 handler_id = find_next_handler_id(); 00088 00089 /* Found one, add the handler */ 00090 hi = g_new0 (HandlerInfo, 1); 00091 00092 hi->handler = handler; 00093 hi->user_data = user_data; 00094 hi->handler_id = handler_id; 00095 00096 handlers = g_list_prepend (handlers, hi); 00097 LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id); 00098 return handler_id; 00099 } 00100 00101 void 00102 qof_event_unregister_handler (gint handler_id) 00103 { 00104 GList *node; 00105 00106 ENTER ("(handler_id=%d)", handler_id); 00107 for (node = handlers; node; node = node->next) 00108 { 00109 HandlerInfo *hi = node->data; 00110 00111 if (hi->handler_id != handler_id) 00112 continue; 00113 00114 /* Normally, we could actually remove the handler's node from the 00115 list, but we may be unregistering the event handler as a result 00116 of a generated event, such as QOF_EVENT_DESTROY. In that case, 00117 we're in the middle of walking the GList and it is wrong to 00118 modify the list. So, instead, we just NULL the handler. */ 00119 if (hi->handler) 00120 LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id, 00121 hi->handler, hi->user_data); 00122 00123 /* safety -- clear the handler in case we're running events now */ 00124 hi->handler = NULL; 00125 00126 if (handler_run_level == 0) 00127 { 00128 handlers = g_list_remove_link (handlers, node); 00129 g_list_free_1 (node); 00130 g_free (hi); 00131 } 00132 else 00133 { 00134 pending_deletes++; 00135 } 00136 00137 return; 00138 } 00139 00140 PERR ("no such handler: %d", handler_id); 00141 } 00142 00143 void 00144 qof_event_suspend (void) 00145 { 00146 suspend_counter++; 00147 00148 if (suspend_counter == 0) 00149 { 00150 PERR ("suspend counter overflow"); 00151 } 00152 } 00153 00154 void 00155 qof_event_resume (void) 00156 { 00157 if (suspend_counter == 0) 00158 { 00159 PERR ("suspend counter underflow"); 00160 return; 00161 } 00162 00163 suspend_counter--; 00164 } 00165 00166 static void 00167 qof_event_generate_internal (QofInstance *entity, QofEventId event_id, 00168 gpointer event_data) 00169 { 00170 GList *node; 00171 GList *next_node = NULL; 00172 gboolean use_old_handlers = FALSE; 00173 00174 g_return_if_fail(entity); 00175 00176 if (event_id <= QOF_EVENT__LAST) 00177 { 00178 use_old_handlers = TRUE; 00179 } 00180 00181 switch (event_id) 00182 { 00183 case QOF_EVENT_NONE: 00184 { 00185 /* if none, don't log, just return. */ 00186 return; 00187 } 00188 } 00189 00190 handler_run_level++; 00191 for (node = handlers; node; node = next_node) 00192 { 00193 HandlerInfo *hi = node->data; 00194 00195 next_node = node->next; 00196 if (hi->handler) 00197 { 00198 PINFO("id=%d hi=%p han=%p data=%p", hi->handler_id, hi, 00199 hi->handler, event_data); 00200 hi->handler (entity, event_id, hi->user_data, event_data); 00201 } 00202 } 00203 handler_run_level--; 00204 00205 /* If we're the outermost event runner and we have pending deletes 00206 * then go delete the handlers now. 00207 */ 00208 if (handler_run_level == 0 && pending_deletes) 00209 { 00210 for (node = handlers; node; node = next_node) 00211 { 00212 HandlerInfo *hi = node->data; 00213 next_node = node->next; 00214 if (hi->handler == NULL) 00215 { 00216 /* remove this node from the list, then free this node */ 00217 handlers = g_list_remove_link (handlers, node); 00218 g_list_free_1 (node); 00219 g_free (hi); 00220 } 00221 } 00222 pending_deletes = 0; 00223 } 00224 } 00225 00226 void 00227 qof_event_force (QofInstance *entity, QofEventId event_id, gpointer event_data) 00228 { 00229 if (!entity) 00230 return; 00231 00232 qof_event_generate_internal (entity, event_id, event_data); 00233 } 00234 00235 void 00236 qof_event_gen (QofInstance *entity, QofEventId event_id, gpointer event_data) 00237 { 00238 if (!entity) 00239 return; 00240 00241 if (suspend_counter) 00242 return; 00243 00244 qof_event_generate_internal (entity, event_id, event_data); 00245 } 00246 00247 /* =========================== END OF FILE ======================= */
1.7.4