gnucash stable: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Mon May 13 00:58:42 EDT 2024


Updated	 via  https://github.com/Gnucash/gnucash/commit/7b46466e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/e54e9d80 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b28ca9bd (commit)
	from  https://github.com/Gnucash/gnucash/commit/579da58a (commit)



commit 7b46466ebd8e8a74ec49610813b2c73f86e9aa3e
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Mon May 13 12:42:26 2024 +0800

    [account.cpp] fix regression caused by 3f7a5a8267
    
    whereby deleting an account and moving all splits to another account
    would segfault. make a copy of priv->splits and work on the copy
    rather than the original.

diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 1fcd9928d9..e82fb8d9c0 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -2251,8 +2251,8 @@ xaccAccountMoveAllSplits (Account *accfrom, Account *accto)
      * Convert each split's amount to accto's commodity.
      * Commit to editing each transaction.
      */
-    std::for_each (from_priv->splits.begin(), from_priv->splits.end(),
-                   [accto](Split *s){ xaccPostSplitMove (s, accto); });
+    auto splits = from_priv->splits;
+    std::for_each (splits.begin(), splits.end(), [accto](auto s){ xaccPostSplitMove (s, accto); });
 
     /* Finally empty accfrom. */
     g_assert(from_priv->splits.empty());

commit e54e9d808677f4b8fb21a546cc5b1232c492cc48
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun May 12 23:58:44 2024 +0800

    [account.cpp] use HashTable for splits
    
    reduces xml loading time from 3.5s to 3.1s, i.e. 11% improvement

diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 1290d1157c..1fcd9928d9 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -333,6 +333,7 @@ gnc_account_init(Account* acc)
     priv->include_sub_account_balances = {};
 
     new (&priv->splits) SplitsVec ();
+    priv->splits_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
     priv->sort_dirty = FALSE;
 }
 
@@ -1470,6 +1471,7 @@ xaccFreeAccount (Account *acc)
     priv->balance_dirty = FALSE;
     priv->sort_dirty = FALSE;
     priv->splits.~SplitsVec();
+    g_hash_table_destroy (priv->splits_hash);
 
     /* qof_instance_release (&acc->inst); */
     g_object_unref(acc);
@@ -1556,6 +1558,7 @@ xaccAccountCommitEdit (Account *acc)
         else
         {
             priv->splits.clear();
+            g_hash_table_remove_all (priv->splits_hash);
         }
 
         /* It turns out there's a case where this assertion does not hold:
@@ -1966,8 +1969,8 @@ gnc_account_insert_split (Account *acc, Split *s)
     g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
 
     priv = GET_PRIVATE(acc);
-    if (std::find (priv->splits.begin(), priv->splits.end(), s) != priv->splits.end())
-        return FALSE;
+    if (!g_hash_table_add (priv->splits_hash, s))
+        return false;
 
     priv->splits.push_back (s);
 
@@ -1997,10 +2000,9 @@ gnc_account_remove_split (Account *acc, Split *s)
 
     priv = GET_PRIVATE(acc);
 
+    if (!g_hash_table_remove (priv->splits_hash, s))
+        return false;
     auto it = std::remove (priv->splits.begin(), priv->splits.end(), s);
-    if (it == priv->splits.end())
-        return FALSE;
-
     priv->splits.erase (it, priv->splits.end());
     //FIXME: find better event type
     qof_event_gen(&acc->inst, QOF_EVENT_MODIFY, nullptr);
diff --git a/libgnucash/engine/AccountP.hpp b/libgnucash/engine/AccountP.hpp
index abd43f69c8..d71f4ef313 100644
--- a/libgnucash/engine/AccountP.hpp
+++ b/libgnucash/engine/AccountP.hpp
@@ -120,6 +120,7 @@ typedef struct AccountPrivate
     gboolean balance_dirty;     /* balances in splits incorrect */
 
     std::vector<Split*> splits;              /* list of split pointers */
+    GHashTable* splits_hash;
     gboolean sort_dirty;        /* sort order of splits is bad */
 
     LotList   *lots;		/* list of lot pointers */

commit b28ca9bdb4781e9dfde0664bf9e1fd109ef9636e
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun May 12 20:16:37 2024 +0800

    use c++ placement new
    
    to initialize non-c++ object members

diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index f164e18720..1290d1157c 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -332,7 +332,7 @@ gnc_account_init(Account* acc)
     priv->lower_balance_limit = {};
     priv->include_sub_account_balances = {};
 
-    priv->splits.clear();
+    new (&priv->splits) SplitsVec ();
     priv->sort_dirty = FALSE;
 }
 
diff --git a/libgnucash/engine/gnc-budget.cpp b/libgnucash/engine/gnc-budget.cpp
index 737c241e5a..ec8638df0c 100644
--- a/libgnucash/engine/gnc-budget.cpp
+++ b/libgnucash/engine/gnc-budget.cpp
@@ -29,7 +29,6 @@
 #include <optional>
 #include <unordered_map>
 #include <vector>
-#include <memory>
 
 #include "Account.h"
 
@@ -84,7 +83,7 @@ typedef struct GncBudgetPrivate
     /* Recurrence (period info) for the budget */
     Recurrence recurrence;
 
-    std::unique_ptr<AcctMap> acct_map;
+    AcctMap acct_map;
 
     /* Number of periods */
     guint  num_periods;
@@ -110,7 +109,7 @@ gnc_budget_init(GncBudget* budget)
     priv = GET_PRIVATE(budget);
     priv->name = CACHE_INSERT(_("Unnamed Budget"));
     priv->description = CACHE_INSERT("");
-    priv->acct_map = std::make_unique<AcctMap>();
+    new (&priv->acct_map) AcctMap ();
 
     priv->num_periods = 12;
     date = gnc_g_date_new_today ();
@@ -280,7 +279,7 @@ gnc_budget_free(QofInstance *inst)
 
     CACHE_REMOVE(priv->name);
     CACHE_REMOVE(priv->description);
-    priv->acct_map = nullptr;   // nullify to ensure unique_ptr is freed.
+    priv->acct_map.~AcctMap();
 
     /* qof_instance_release (&budget->inst); */
     g_object_unref(budget);
@@ -477,12 +476,8 @@ gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
 
     gnc_budget_begin_edit(budget);
     priv->num_periods = num_periods;
-    std::for_each (priv->acct_map->begin(),
-                   priv->acct_map->end(),
-                   [num_periods](auto& it)
-                   {
-                       it.second.resize(num_periods);
-                   });
+    std::for_each (priv->acct_map.begin(), priv->acct_map.end(),
+                   [num_periods](auto& it){ it.second.resize(num_periods); });
     qof_instance_set_dirty(&budget->inst);
     gnc_budget_commit_edit(budget);
 
@@ -681,7 +676,7 @@ get_perioddata (const GncBudget *budget, const Account *account, guint period_nu
     if (period_num >= priv->num_periods)
         throw std::out_of_range("period_num >= num_periods");
 
-    auto& vec = priv->acct_map->operator[](account);
+    auto& vec = priv->acct_map[account];
 
     if (vec.empty())
     {



Summary of changes:
 libgnucash/engine/Account.cpp    | 18 ++++++++++--------
 libgnucash/engine/AccountP.hpp   |  1 +
 libgnucash/engine/gnc-budget.cpp | 17 ++++++-----------
 3 files changed, 17 insertions(+), 19 deletions(-)



More information about the gnucash-changes mailing list