vcl/inc/vcleventlisteners.hxx | 1 + vcl/source/app/vclevent.cxx | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-)
New commits: commit 9402579be9d9a8888af03291edd2478a716f901a Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Mon Oct 11 15:23:00 2021 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Mon Oct 11 21:52:43 2021 +0200 avoid O(n^2) in VclEventListeners::Call() if possible The list seems to only rarely change. Change-Id: Ib1263c696619908a2792c67ff04c5a0c5f0a7858 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123414 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/vcl/inc/vcleventlisteners.hxx b/vcl/inc/vcleventlisteners.hxx index 47a84e3b80bc..a1e34d397d02 100644 --- a/vcl/inc/vcleventlisteners.hxx +++ b/vcl/inc/vcleventlisteners.hxx @@ -31,6 +31,7 @@ public: private: std::vector<Link<VclSimpleEvent&, void>> m_aListeners; + mutable bool m_updated = false; }; #endif // INCLUDED_VCL_INC_VCLEVENTLISTENERS_HXX diff --git a/vcl/source/app/vclevent.cxx b/vcl/source/app/vclevent.cxx index af6ff02a15a8..b99c6987fe97 100644 --- a/vcl/source/app/vclevent.cxx +++ b/vcl/source/app/vclevent.cxx @@ -32,6 +32,7 @@ void VclEventListeners::Call( VclSimpleEvent& rEvent ) const std::vector<Link<VclSimpleEvent&,void>> aCopy( m_aListeners ); std::vector<Link<VclSimpleEvent&,void>>::iterator aIter( aCopy.begin() ); std::vector<Link<VclSimpleEvent&,void>>::const_iterator aEnd( aCopy.end() ); + m_updated = false; if (VclWindowEvent* pWindowEvent = dynamic_cast<VclWindowEvent*>(&rEvent)) { VclPtr<vcl::Window> xWin(pWindowEvent->GetWindow()); @@ -40,7 +41,8 @@ void VclEventListeners::Call( VclSimpleEvent& rEvent ) const { Link<VclSimpleEvent&,void> &rLink = *aIter; // check this hasn't been removed in some re-enterancy scenario fdo#47368 - if( std::find(m_aListeners.begin(), m_aListeners.end(), rLink) != m_aListeners.end() ) + // But only check if the list actually has been changed. + if( !m_updated || std::find(m_aListeners.begin(), m_aListeners.end(), rLink) != m_aListeners.end() ) rLink.Call( rEvent ); ++aIter; } @@ -50,7 +52,7 @@ void VclEventListeners::Call( VclSimpleEvent& rEvent ) const while ( aIter != aEnd ) { Link<VclSimpleEvent&,void> &rLink = *aIter; - if( std::find(m_aListeners.begin(), m_aListeners.end(), rLink) != m_aListeners.end() ) + if( !m_updated || std::find(m_aListeners.begin(), m_aListeners.end(), rLink) != m_aListeners.end() ) rLink.Call( rEvent ); ++aIter; } @@ -60,11 +62,13 @@ void VclEventListeners::Call( VclSimpleEvent& rEvent ) const void VclEventListeners::addListener( const Link<VclSimpleEvent&,void>& rListener ) { m_aListeners.push_back( rListener ); + m_updated = true; } void VclEventListeners::removeListener( const Link<VclSimpleEvent&,void>& rListener ) { m_aListeners.erase( std::remove(m_aListeners.begin(), m_aListeners.end(), rListener ), m_aListeners.end() ); + m_updated = true; } VclWindowEvent::VclWindowEvent( vcl::Window* pWin, VclEventId n, void* pDat ) : VclSimpleEvent(n)