include/svl/undo.hxx            |    4 +++-
 svl/source/undo/undo.cxx        |    8 +++++---
 sw/source/core/undo/docundo.cxx |    3 ++-
 3 files changed, 10 insertions(+), 5 deletions(-)

New commits:
commit a368b4321a8f1584939cbc1f2bc2c4ac83ddb97d
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Mon Mar 10 21:22:22 2025 +0200
Commit:     Noel Grandin <noelgran...@gmail.com>
CommitDate: Tue Mar 11 08:16:39 2025 +0100

    tdf#136238 Speedup deleting a very very large cross page table
    
    We have a very large nested/list action here, which means
    that RemoveOldestUndoAction() cannot do anything, and we spin
    in the loop in sw::UndoManager::AddUndoAction
    
    So we need to break out of that loop in this situation, which
    makes the delete almost instantaneous.
    
    Change-Id: Ia2bd9c0fd00c6551e99ae09154ecf0f680b9fcea
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182748
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx
index 2ca0f3b0f8a4..fc4485bde602 100644
--- a/include/svl/undo.hxx
+++ b/include/svl/undo.hxx
@@ -302,8 +302,10 @@ public:
     bool            HasTopUndoActionMark( UndoStackMark const i_mark );
 
     /** removes the oldest Undo actions from the stack
+    * @returns false if it could not do anything (can happen when the action 
is very large)
     */
-    void            RemoveOldestUndoAction();
+    [[nodiscard]]
+    bool            RemoveOldestUndoAction();
 
     void dumpAsXml(xmlTextWriterPtr pWriter) const;
 
diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index cb278cf153c3..70f9411c28bf 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -1173,19 +1173,21 @@ void SfxUndoManager::UndoMark(UndoStackMark i_mark)
 }
 
 
-void SfxUndoManager::RemoveOldestUndoAction()
+bool SfxUndoManager::RemoveOldestUndoAction()
 {
     UndoManagerGuard aGuard( *m_xData );
 
     if ( IsInListAction() && ( m_xData->maUndoArray.nCurUndoAction == 1 ) )
     {
-        assert(!"SfxUndoManager::RemoveOldestUndoActions: cannot remove a 
not-yet-closed list action!");
-        return;
+        // this can happen if we are performing a very large writer edit (e.g. 
removing a very large table)
+        SAL_WARN("svl", "SfxUndoManager::RemoveOldestUndoActions: cannot 
remove a not-yet-closed list action!");
+        return false;
     }
 
     aGuard.markForDeletion( m_xData->maUndoArray.Remove( 0 ) );
     --m_xData->maUndoArray.nCurUndoAction;
     ImplCheckEmptyActions();
+    return true;
 }
 
 void SfxUndoManager::dumpAsXml(xmlTextWriterPtr pWriter) const
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
index 576b0579e1e8..786bd3762815 100644
--- a/sw/source/core/undo/docundo.cxx
+++ b/sw/source/core/undo/docundo.cxx
@@ -629,7 +629,8 @@ void 
UndoManager::AddUndoAction(std::unique_ptr<SfxUndoAction> pAction, bool bTr
     // if the undo nodes array is too large, delete some actions
     while (UNDO_ACTION_LIMIT < sal_Int32(GetUndoNodes().Count()))
     {
-        RemoveOldestUndoAction();
+        if (!RemoveOldestUndoAction())
+            break;
     }
 }
 

Reply via email to