summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-10-11 15:23:00 +0200
committerLuboš Luňák <l.lunak@collabora.com>2021-10-11 21:52:43 +0200
commit9402579be9d9a8888af03291edd2478a716f901a (patch)
treef25c10eb9b4711f74a3c849fd320653579e45dc6
parent1c46d2cabfa9cffd65599e55ca4060e39dcbad62 (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>
-rw-r--r--vcl/inc/vcleventlisteners.hxx1
-rw-r--r--vcl/source/app/vclevent.cxx8
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)