qofevent.c

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, gpointer user_data)
00075 {
00076   HandlerInfo *hi;
00077   gint handler_id;
00078 
00079   ENTER ("(handler=%p, data=%p)", handler, user_data);
00080 
00081   /* sanity check */
00082   if (!handler)
00083   {
00084     PERR ("no handler specified");
00085     return 0;
00086   }
00087   PINFO (" deprecated handler specified");
00088 
00089   handler_id = find_next_handler_id();
00090   /* Found one, add the handler */
00091   hi = g_new0 (HandlerInfo, 1);
00092 
00093   hi->old_handler = handler;
00094   hi->user_data = user_data;
00095   hi->handler_id = handler_id;
00096 
00097   handlers = g_list_prepend (handlers, hi);
00098 
00099   LEAVE (" (handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id);
00100   return handler_id;
00101 
00102 }
00103 #endif /* QOF_DISABLE_DEPRECATED */
00104 
00105 gint
00106 qof_event_register_handler (QofEventHandler handler, gpointer user_data)
00107 {
00108   HandlerInfo *hi;
00109   gint handler_id;
00110 
00111   ENTER ("(handler=%p, data=%p)", handler, user_data);
00112 
00113   /* sanity check */
00114   if (!handler)
00115   {
00116     PERR ("no handler specified");
00117     return 0;
00118   }
00119 
00120   /* look for a free handler id */
00121   handler_id = find_next_handler_id();
00122 
00123   /* Found one, add the handler */
00124   hi = g_new0 (HandlerInfo, 1);
00125 
00126   hi->handler = handler;
00127   hi->user_data = user_data;
00128   hi->handler_id = handler_id;
00129 
00130   handlers = g_list_prepend (handlers, hi);
00131   LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id);
00132   return handler_id;
00133 }
00134 
00135 void
00136 qof_event_unregister_handler (gint handler_id)
00137 {
00138   GList *node;
00139 
00140   ENTER ("(handler_id=%d)", handler_id);
00141   for (node = handlers; node; node = node->next)
00142   {
00143     HandlerInfo *hi = node->data;
00144 
00145     if (hi->handler_id != handler_id)
00146       continue;
00147 
00148     /* Normally, we could actually remove the handler's node from the
00149        list, but we may be unregistering the event handler as a result
00150        of a generated event, such as GNC_EVENT_DESTROY.  In that case,
00151        we're in the middle of walking the GList and it is wrong to
00152        modify the list. So, instead, we just NULL the handler. */ 
00153     if(hi->handler) 
00154     LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
00155            hi->handler, hi->user_data);
00156 #ifndef QOF_DISABLE_DEPRECATED
00157     if(hi->old_handler) 
00158         LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
00159            hi->old_handler, hi->user_data);
00160 #endif
00161 
00162     /* safety -- clear the handler in case we're running events now */
00163     hi->handler = NULL;
00164 #ifndef QOF_DISABLE_DEPRECATED
00165     hi->old_handler = NULL;
00166 #endif
00167 
00168     if (handler_run_level == 0) {
00169       handlers = g_list_remove_link (handlers, node);
00170       g_list_free_1 (node);
00171       g_free (hi);
00172     } else {
00173       pending_deletes++;
00174     }
00175 
00176     return;
00177   }
00178 
00179   PERR ("no such handler: %d", handler_id);
00180 }
00181 
00182 void
00183 qof_event_suspend (void)
00184 {
00185   suspend_counter++;
00186 
00187   if (suspend_counter == 0)
00188   {
00189     PERR ("suspend counter overflow");
00190   }
00191 }
00192 
00193 void
00194 qof_event_resume (void)
00195 {
00196   if (suspend_counter == 0)
00197   {
00198     PERR ("suspend counter underflow");
00199     return;
00200   }
00201 
00202   suspend_counter--;
00203 }
00204 
00205 static void
00206 qof_event_generate_internal (QofEntity *entity, QofEventId event_id, 
00207                             gpointer event_data)
00208 {
00209   GList *node;
00210   GList *next_node = NULL;
00211   gboolean use_old_handlers = FALSE;
00212 
00213   g_return_if_fail(entity);
00214 
00215   if (event_id <= QOF_EVENT__LAST)
00216   {
00217     use_old_handlers = TRUE;
00218   }
00219         
00220   switch (event_id)
00221   {
00222           case QOF_EVENT_NONE: { 
00223                 /* if none, don't log, just return. */
00224                 return;
00225           }
00226   }
00227 
00228   handler_run_level++;
00229   for (node = handlers; node; node = next_node)
00230   {
00231     HandlerInfo *hi = node->data;
00232 
00233     next_node = node->next;
00234 #ifndef QOF_DISABLE_DEPRECATED
00235     if ((hi->old_handler) && (use_old_handlers))
00236     {
00237       PINFO(" deprecated: id=%d hi=%p han=%p", hi->handler_id, hi, 
00238             hi->old_handler);
00239       hi->old_handler ((GUID *)&entity->guid, entity->e_type,
00240                        event_id, hi->user_data);
00241     }
00242 #endif
00243     if (hi->handler)
00244     {
00245       PINFO("id=%d hi=%p han=%p data=%p", hi->handler_id, hi, 
00246             hi->handler, event_data);
00247       hi->handler (entity, event_id, hi->user_data, event_data);
00248     }
00249   }
00250   handler_run_level--;
00251 
00252   /* If we're the outtermost event runner and we have pending deletes
00253    * then go delete the handlers now.
00254    */
00255   if (handler_run_level == 0 && pending_deletes)
00256   {
00257     for (node = handlers; node; node = next_node)
00258     {
00259       HandlerInfo *hi = node->data;
00260       next_node = node->next;
00261       if ((hi->handler == NULL)
00262 #ifndef QOF_DISABLE_DEPRECATED
00263          &&(hi->old_handler == NULL)
00264 #endif
00265          )
00266       {
00267         /* remove this node from the list, then free this node */
00268         handlers = g_list_remove_link (handlers, node);
00269         g_list_free_1 (node);
00270         g_free (hi);
00271       }
00272     }
00273     pending_deletes = 0;
00274   }
00275 }
00276 
00277 void
00278 qof_event_force (QofEntity *entity, QofEventId event_id, gpointer event_data)
00279 {
00280   if (!entity)
00281     return;
00282 
00283   qof_event_generate_internal (entity, event_id, event_data);
00284 }
00285 
00286 void
00287 qof_event_gen (QofEntity *entity, QofEventId event_id, gpointer event_data)
00288 {
00289   if (!entity)
00290     return;
00291 
00292   if (suspend_counter)
00293     return;
00294 
00295   qof_event_generate_internal (entity, event_id, event_data);
00296 }
00297 
00298 /* deprecated */
00299 void 
00300 qof_event_generate (const GUID *guid, QofIdType e_type, 
00301                                         QofEventId event_id)
00302 {
00303   QofEntity ent;
00304   ent.guid = *guid;
00305   ent.e_type = e_type;
00306   if (suspend_counter) return;
00307   /* caution: this is an incomplete entity! */
00308   qof_event_generate_internal (&ent, event_id, NULL);
00309 }
00310 
00311 /* =========================== END OF FILE ======================= */

Generated on Fri May 12 17:57:20 2006 for QOF by  doxygen 1.4.4