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)

Reply via email to