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.grandin@collabora.co.uk>
Tested-by: Jenkins
This commit is contained in:
Noel Grandin 2025-03-10 21:22:22 +02:00
parent dcfc32914f
commit a368b4321a
3 changed files with 10 additions and 5 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;
}
}