diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2021-10-11 15:23:00 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2021-10-11 21:52:43 +0200 |
commit | 9402579be9d9a8888af03291edd2478a716f901a (patch) | |
tree | f25c10eb9b4711f74a3c849fd320653579e45dc6 /vcl | |
parent | 1c46d2cabfa9cffd65599e55ca4060e39dcbad62 (diff) |
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.lunak@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/vcleventlisteners.hxx | 1 | ||||
-rw-r--r-- | vcl/source/app/vclevent.cxx | 8 |
2 files changed, 7 insertions, 2 deletions
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) |