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: 2025-02-07 16:25:45 Functions: 100.0 % 8 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     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                 :         222 : 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                 :         222 :     handler_id = next_handler_id;
      52                 :         222 :     node = handlers;
      53                 :             : 
      54                 :         648 :     while (node)
      55                 :             :     {
      56                 :         426 :         hi = static_cast<HandlerInfo*>(node->data);
      57                 :             : 
      58                 :         426 :         if (hi->handler_id == handler_id)
      59                 :             :         {
      60                 :           0 :             handler_id++;
      61                 :           0 :             node = handlers;
      62                 :           0 :             continue;
      63                 :             :         }
      64                 :             : 
      65                 :         426 :         node = node->next;
      66                 :             :     }
      67                 :             :     /* Update id for next registration */
      68                 :         222 :     next_handler_id = handler_id + 1;
      69                 :         222 :     return handler_id;
      70                 :             : }
      71                 :             : 
      72                 :             : gint
      73                 :         222 : qof_event_register_handler (QofEventHandler handler, gpointer user_data)
      74                 :             : {
      75                 :             :     HandlerInfo *hi;
      76                 :             :     gint handler_id;
      77                 :             : 
      78                 :         222 :     ENTER ("(handler=%p, data=%p)", handler, user_data);
      79                 :             : 
      80                 :             :     /* sanity check */
      81                 :         222 :     if (!handler)
      82                 :             :     {
      83                 :           0 :         PERR ("no handler specified");
      84                 :           0 :         return 0;
      85                 :             :     }
      86                 :             : 
      87                 :             :     /* look for a free handler id */
      88                 :         222 :     handler_id = find_next_handler_id();
      89                 :             : 
      90                 :             :     /* Found one, add the handler */
      91                 :         222 :     hi = g_new0 (HandlerInfo, 1);
      92                 :             : 
      93                 :         222 :     hi->handler = handler;
      94                 :         222 :     hi->user_data = user_data;
      95                 :         222 :     hi->handler_id = handler_id;
      96                 :             : 
      97                 :         222 :     handlers = g_list_prepend (handlers, hi);
      98                 :         222 :     LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id);
      99                 :         222 :     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                 :         150 : qof_event_suspend (void)
     146                 :             : {
     147                 :         150 :     suspend_counter++;
     148                 :             : 
     149                 :         150 :     if (suspend_counter == 0)
     150                 :             :     {
     151                 :           0 :         PERR ("suspend counter overflow");
     152                 :             :     }
     153                 :         150 : }
     154                 :             : 
     155                 :             : void
     156                 :         150 : qof_event_resume (void)
     157                 :             : {
     158                 :         150 :     if (suspend_counter == 0)
     159                 :             :     {
     160                 :           0 :         PERR ("suspend counter underflow");
     161                 :           0 :         return;
     162                 :             :     }
     163                 :             : 
     164                 :         150 :     suspend_counter--;
     165                 :             : }
     166                 :             : 
     167                 :             : static void
     168                 :      755504 : qof_event_generate_internal (QofInstance *entity, QofEventId event_id,
     169                 :             :                              gpointer event_data)
     170                 :             : {
     171                 :             :     GList *node;
     172                 :      755504 :     GList *next_node = NULL;
     173                 :             : 
     174                 :      755504 :     g_return_if_fail(entity);
     175                 :             : 
     176                 :      755504 :     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                 :      755503 :     handler_run_level++;
     186                 :     1121737 :     for (node = handlers; node; node = next_node)
     187                 :             :     {
     188                 :      366234 :         HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
     189                 :             : 
     190                 :      366234 :         next_node = node->next;
     191                 :      366234 :         if (hi->handler)
     192                 :             :         {
     193                 :      366234 :             PINFO("id=%d hi=%p han=%p data=%p", hi->handler_id, hi,
     194                 :             :                   hi->handler, event_data);
     195                 :      366234 :             hi->handler (entity, event_id, hi->user_data, event_data);
     196                 :             :         }
     197                 :             :     }
     198                 :      755503 :     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                 :      755503 :     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                 :         458 : qof_event_force (QofInstance *entity, QofEventId event_id, gpointer event_data)
     223                 :             : {
     224                 :         458 :     if (!entity)
     225                 :           0 :         return;
     226                 :             : 
     227                 :         458 :     qof_event_generate_internal (entity, event_id, event_data);
     228                 :             : }
     229                 :             : 
     230                 :             : void
     231                 :      755204 : qof_event_gen (QofInstance *entity, QofEventId event_id, gpointer event_data)
     232                 :             : {
     233                 :      755204 :     if (!entity)
     234                 :          10 :         return;
     235                 :             : 
     236                 :      755194 :     if (suspend_counter)
     237                 :         148 :         return;
     238                 :             : 
     239                 :      755046 :     qof_event_generate_internal (entity, event_id, event_data);
     240                 :             : }
     241                 :             : 
     242                 :             : /* =========================== END OF FILE ======================= */
        

Generated by: LCOV version 2.0-1