diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-08-12 13:06:25 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-08-12 14:17:15 +0200 |
commit | df6a8b15a67baa6e2717a7de7755ac93fdb46723 (patch) | |
tree | f00335d58e5ccb400a6ca5d7d110981fae7715d1 /sc | |
parent | a72f2dcf73df9b9f4420cc93aa57a77c165a0fcb (diff) |
tdf#95549 speed up xls open
Remove the m_wThis field, and instead just check the ref count to know
if we are being called from our own destructor.
Also re-order ScCellRangesBase::Notify so we do the cheap checks first.
This shaves 2% off the load time
Change-Id: Ie95a4ff46bacba583ec4b3a934f98a9aac3551b9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120385
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/cellsuno.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/unoobj/cellsuno.cxx | 145 |
2 files changed, 58 insertions, 88 deletions
diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx index b29da7c92c0b..7f1b1a0106ad 100644 --- a/sc/inc/cellsuno.hxx +++ b/sc/inc/cellsuno.hxx @@ -176,7 +176,6 @@ class SC_DLLPUBLIC ScCellRangesBase : friend class ooo::vba::excel::ScVbaCellRangeAccess; private: - css::uno::WeakReference<css::uno::XInterface> m_wThis; const SfxItemPropertySet* pPropSet; ScDocShell* pDocShell; std::unique_ptr<ScLinkListener> pValueListener; diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index 8828d4dd2af8..6e829f2568eb 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -1377,15 +1377,6 @@ ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRange& rR) : bGotDataChangedHint( false ), aValueListeners( 0 ) { - // this is a hack to get m_wThis initialized; ideally there would be - // factory functions doing this but there are so many subclasses of this... - osl_atomic_increment(&m_refCount); - { - m_wThis = uno::Reference<uno::XInterface>( - static_cast<cppu::OWeakObject*>(this)); - } - osl_atomic_decrement(&m_refCount); - ScRange aCellRange(rR); aCellRange.PutInOrder(); aRanges.push_back( aCellRange ); @@ -1409,15 +1400,6 @@ ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRangeList& rR) : bGotDataChangedHint( false ), aValueListeners( 0 ) { - // this is a hack to get m_wThis initialized; ideally there would be - // factory functions doing this but there are so many subclasses of this... - osl_atomic_increment(&m_refCount); - { - m_wThis = uno::Reference<uno::XInterface>( - static_cast<cppu::OWeakObject*>(this)); - } - osl_atomic_decrement(&m_refCount); - if (pDocShell) // Null if created with createInstance { ScDocument& rDoc = pDocShell->GetDocument(); @@ -1513,17 +1495,65 @@ const ScMarkData* ScCellRangesBase::GetMarkData() void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) { - uno::Reference<uno::XInterface> const xThis(m_wThis); - if (!xThis.is()) - { // fdo#72695: if UNO object is already dead, don't revive it with event - if (SfxHintId::Dying == rHint.GetId()) - { // if the document dies, must reset to avoid crash in dtor! - ForgetCurrentAttrs(); - pDocShell = nullptr; + const SfxHintId nId = rHint.GetId(); + if ( nId == SfxHintId::Dying ) + { + // if the document dies, must reset to avoid crash in dtor! + ForgetCurrentAttrs(); + pDocShell = nullptr; // invalid + + // fdo#72695: if UNO object is already dead, don't revive it with event + if ( m_refCount > 0 && !aValueListeners.empty() ) + { + // dispose listeners + + lang::EventObject aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + for (uno::Reference<util::XModifyListener> & xValueListener : aValueListeners) + xValueListener->disposing( aEvent ); + + aValueListeners.clear(); + + // The listeners can't have the last ref to this, as it's still held + // by the DocShell. } - return; } - if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) ) + else if ( nId == SfxHintId::DataChanged ) + { + // document content changed -> forget cached attributes + ForgetCurrentAttrs(); + + if ( bGotDataChangedHint && pDocShell ) + { + // This object was notified of content changes, so one call + // for each listener is generated now. + // The calls can't be executed directly because the document's + // UNO broadcaster list must not be modified. + // Instead, add to the document's list of listener calls, + // which will be executed directly after the broadcast of + // SfxHintId::DataChanged. + + lang::EventObject aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + + // the EventObject holds a Ref to this object until after the listener calls + + ScDocument& rDoc = pDocShell->GetDocument(); + for (const uno::Reference<util::XModifyListener> & xValueListener : aValueListeners) + rDoc.AddUnoListenerCall( xValueListener, aEvent ); + + bGotDataChangedHint = false; + } + } + else if ( nId == SfxHintId::ScCalcAll ) + { + // broadcast from DoHardRecalc - set bGotDataChangedHint + // (SfxHintId::DataChanged follows separately) + + if ( !aValueListeners.empty() ) + bGotDataChangedHint = true; + } + else if ( auto pRefHint = dynamic_cast<const ScUpdateRefHint*>(&rHint) ) { ScDocument& rDoc = pDocShell->GetDocument(); std::unique_ptr<ScRangeList> pUndoRanges; @@ -1535,7 +1565,7 @@ void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) { if ( pRefHint->GetMode() == URM_INSDEL && aRanges.size() == 1 - && comphelper::getUnoTunnelImplementation<ScTableSheetObj>(xThis) + && dynamic_cast<ScTableSheetObj*>(this) ) { // #101755#; the range size of a sheet does not change @@ -1568,65 +1598,6 @@ void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) bGotDataChangedHint = true; // need to broadcast the undo, too } } - else - { - const SfxHintId nId = rHint.GetId(); - if ( nId == SfxHintId::Dying ) - { - ForgetCurrentAttrs(); - pDocShell = nullptr; // invalid - - if ( !aValueListeners.empty() ) - { - // dispose listeners - - lang::EventObject aEvent; - aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); - for (uno::Reference<util::XModifyListener> & xValueListener : aValueListeners) - xValueListener->disposing( aEvent ); - - aValueListeners.clear(); - - // The listeners can't have the last ref to this, as it's still held - // by the DocShell. - } - } - else if ( nId == SfxHintId::DataChanged ) - { - // document content changed -> forget cached attributes - ForgetCurrentAttrs(); - - if ( bGotDataChangedHint && pDocShell ) - { - // This object was notified of content changes, so one call - // for each listener is generated now. - // The calls can't be executed directly because the document's - // UNO broadcaster list must not be modified. - // Instead, add to the document's list of listener calls, - // which will be executed directly after the broadcast of - // SfxHintId::DataChanged. - - lang::EventObject aEvent; - aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); - - // the EventObject holds a Ref to this object until after the listener calls - - ScDocument& rDoc = pDocShell->GetDocument(); - for (const uno::Reference<util::XModifyListener> & xValueListener : aValueListeners) - rDoc.AddUnoListenerCall( xValueListener, aEvent ); - - bGotDataChangedHint = false; - } - } - else if ( nId == SfxHintId::ScCalcAll ) - { - // broadcast from DoHardRecalc - set bGotDataChangedHint - // (SfxHintId::DataChanged follows separately) - - if ( !aValueListeners.empty() ) - bGotDataChangedHint = true; - } - } } void ScCellRangesBase::RefChanged() |