LCOV - code coverage report
Current view: top level - libgnucash/engine - qofevent.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 89.3 % 84 75
Test Date: 2026-11-02 18:19:43 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            Line data    Source code
       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              : 
      28              : #include "qof.h"
      29              : #include "qofevent-p.h"
      30              : 
      31              : /* Static Variables ************************************************/
      32              : static guint   suspend_counter   = 0;
      33              : static gint    next_handler_id   = 1;
      34              : static guint   handler_run_level = 0;
      35              : static guint   pending_deletes   = 0;
      36              : static GList   *handlers  =   NULL;
      37              : 
      38              : /* This static indicates the debugging module that this .o belongs to.  */
      39              : static QofLogModule log_module = QOF_MOD_ENGINE;
      40              : 
      41              : /* Implementations *************************************************/
      42              : 
      43              : static gint
      44          226 : find_next_handler_id(void)
      45              : {
      46              :     HandlerInfo *hi;
      47              :     gint handler_id;
      48              :     GList *node;
      49              : 
      50              :     /* look for a free handler id */
      51          226 :     handler_id = next_handler_id;
      52          226 :     node = handlers;
      53              : 
      54          655 :     while (node)
      55              :     {
      56          429 :         hi = static_cast<HandlerInfo*>(node->data);
      57              : 
      58          429 :         if (hi->handler_id == handler_id)
      59              :         {
      60            0 :             handler_id++;
      61            0 :             node = handlers;
      62            0 :             continue;
      63              :         }
      64              : 
      65          429 :         node = node->next;
      66              :     }
      67              :     /* Update id for next registration */
      68          226 :     next_handler_id = handler_id + 1;
      69          226 :     return handler_id;
      70              : }
      71              : 
      72              : gint
      73          226 : qof_event_register_handler (QofEventHandler handler, gpointer user_data)
      74              : {
      75              :     HandlerInfo *hi;
      76              :     gint handler_id;
      77              : 
      78          226 :     ENTER ("(handler=%p, data=%p)", handler, user_data);
      79              : 
      80              :     /* sanity check */
      81          226 :     if (!handler)
      82              :     {
      83            0 :         PERR ("no handler specified");
      84            0 :         return 0;
      85              :     }
      86              : 
      87              :     /* look for a free handler id */
      88          226 :     handler_id = find_next_handler_id();
      89              : 
      90              :     /* Found one, add the handler */
      91          226 :     hi = g_new0 (HandlerInfo, 1);
      92              : 
      93          226 :     hi->handler = handler;
      94          226 :     hi->user_data = user_data;
      95          226 :     hi->handler_id = handler_id;
      96              : 
      97          226 :     handlers = g_list_prepend (handlers, hi);
      98          226 :     LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id);
      99          226 :     return handler_id;
     100              : }
     101              : 
     102              : void
     103          198 : qof_event_unregister_handler (gint handler_id)
     104              : {
     105              :     GList *node;
     106              : 
     107          198 :     ENTER ("(handler_id=%d)", handler_id);
     108          243 :     for (node = handlers; node; node = node->next)
     109              :     {
     110          237 :         HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
     111              : 
     112          237 :         if (hi->handler_id != handler_id)
     113           45 :             continue;
     114              : 
     115              :         /* Normally, we could actually remove the handler's node from the
     116              :            list, but we may be unregistering the event handler as a result
     117              :            of a generated event, such as QOF_EVENT_DESTROY.  In that case,
     118              :            we're in the middle of walking the GList and it is wrong to
     119              :            modify the list. So, instead, we just NULL the handler. */
     120          192 :         if (hi->handler)
     121          192 :             LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
     122              :                    hi->handler, hi->user_data);
     123              : 
     124              :         /* safety -- clear the handler in case we're running events now */
     125          192 :         hi->handler = NULL;
     126              : 
     127          192 :         if (handler_run_level == 0)
     128              :         {
     129          191 :             handlers = g_list_remove_link (handlers, node);
     130          191 :             g_list_free_1 (node);
     131          191 :             g_free (hi);
     132              :         }
     133              :         else
     134              :         {
     135            1 :             pending_deletes++;
     136              :         }
     137              : 
     138          192 :         return;
     139              :     }
     140              : 
     141            6 :     PERR ("no such handler: %d", handler_id);
     142              : }
     143              : 
     144              : void
     145          162 : qof_event_suspend (void)
     146              : {
     147          162 :     suspend_counter++;
     148              : 
     149          162 :     if (suspend_counter == 0)
     150              :     {
     151            0 :         PERR ("suspend counter overflow");
     152              :     }
     153          162 : }
     154              : 
     155              : void
     156          162 : qof_event_resume (void)
     157              : {
     158          162 :     if (suspend_counter == 0)
     159              :     {
     160            0 :         PERR ("suspend counter underflow");
     161            0 :         return;
     162              :     }
     163              : 
     164          162 :     suspend_counter--;
     165              : }
     166              : 
     167              : static void
     168       839312 : qof_event_generate_internal (QofInstance *entity, QofEventId event_id,
     169              :                              gpointer event_data)
     170              : {
     171              :     GList *node;
     172       839312 :     GList *next_node = NULL;
     173              : 
     174       839312 :     g_return_if_fail(entity);
     175              : 
     176       839312 :     switch (event_id)
     177              :     {
     178            1 :     case QOF_EVENT_NONE:
     179              :     {
     180              :         /* if none, don't log, just return. */
     181            1 :         return;
     182              :     }
     183              :     }
     184              : 
     185       839311 :     handler_run_level++;
     186      1390865 :     for (node = handlers; node; node = next_node)
     187              :     {
     188       551554 :         HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
     189              : 
     190       551554 :         next_node = node->next;
     191       551554 :         if (hi->handler)
     192              :         {
     193       551554 :             PINFO("id=%d hi=%p han=%p data=%p", hi->handler_id, hi,
     194              :                   hi->handler, event_data);
     195       551554 :             hi->handler (entity, event_id, hi->user_data, event_data);
     196              :         }
     197              :     }
     198       839311 :     handler_run_level--;
     199              : 
     200              :     /* If we're the outermost event runner and we have pending deletes
     201              :      * then go delete the handlers now.
     202              :      */
     203       839311 :     if (handler_run_level == 0 && pending_deletes)
     204              :     {
     205            3 :         for (node = handlers; node; node = next_node)
     206              :         {
     207            2 :             HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
     208            2 :             next_node = node->next;
     209            2 :             if (hi->handler == NULL)
     210              :             {
     211              :                 /* remove this node from the list, then free this node */
     212            1 :                 handlers = g_list_remove_link (handlers, node);
     213            1 :                 g_list_free_1 (node);
     214            1 :                 g_free (hi);
     215              :             }
     216              :         }
     217            1 :         pending_deletes = 0;
     218              :     }
     219              : }
     220              : 
     221              : void
     222          500 : qof_event_force (QofInstance *entity, QofEventId event_id, gpointer event_data)
     223              : {
     224          500 :     if (!entity)
     225            0 :         return;
     226              : 
     227          500 :     qof_event_generate_internal (entity, event_id, event_data);
     228              : }
     229              : 
     230              : void
     231       838970 : qof_event_gen (QofInstance *entity, QofEventId event_id, gpointer event_data)
     232              : {
     233       838970 :     if (!entity)
     234           10 :         return;
     235              : 
     236       838960 :     if (suspend_counter)
     237          148 :         return;
     238              : 
     239       838812 :     qof_event_generate_internal (entity, event_id, event_data);
     240              : }
     241              : 
     242              : /* =========================== END OF FILE ======================= */
        

Generated by: LCOV version 2.0-1