diff options
author | David Tardon <dtardon@redhat.com> | 2016-05-06 09:33:37 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2016-05-06 09:43:01 +0200 |
commit | 2fb31f248fe86c52c1070cbc8b18b24872a4bedc (patch) | |
tree | e275a2e0a34d1e125fec1c72fc7cc540078209f3 /vcl | |
parent | tdf#99703 Revert "improve perf. of VCL event dispatch" (diff) | |
download | core-2fb31f248fe86c52c1070cbc8b18b24872a4bedc.tar.gz core-2fb31f248fe86c52c1070cbc8b18b24872a4bedc.zip |
improve perf. of VCL event dispatch, take II
Change-Id: I5052f0c3e2c8739b336da52ef9590e5008255247
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/window.h | 2 | ||||
-rw-r--r-- | vcl/source/window/event.cxx | 15 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 1 |
3 files changed, 17 insertions, 1 deletions
diff --git a/vcl/inc/window.h b/vcl/inc/window.h index e06a6b1d07c9..302e9d03541b 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -201,6 +201,8 @@ public: VclPtr<vcl::Window> mpLastFocusWindow; VclPtr<vcl::Window> mpDlgCtrlDownWindow; std::vector<Link<VclWindowEvent&,void>> maEventListeners; + int mnEventListenersIteratingCount; + std::set<Link<VclWindowEvent&,void>> maEventListenersDeleted; std::vector<Link<VclWindowEvent&,void>> maChildEventListeners; int mnChildEventListenersIteratingCount; std::set<Link<VclWindowEvent&,void>> maChildEventListenersDeleted; diff --git a/vcl/source/window/event.cxx b/vcl/source/window/event.cxx index 10a85ed368db..c7d17778f9cd 100644 --- a/vcl/source/window/event.cxx +++ b/vcl/source/window/event.cxx @@ -216,11 +216,22 @@ void Window::CallEventListeners( sal_uLong nEvent, void* pData ) { // Copy the list, because this can be destroyed when calling a Link... std::vector<Link<VclWindowEvent&,void>> aCopy( mpWindowImpl->maEventListeners ); + // we use an iterating counter/flag and a set of deleted Link's to avoid O(n^2) behaviour + mpWindowImpl->mnEventListenersIteratingCount++; + auto& rWindowImpl = *mpWindowImpl; + comphelper::ScopeGuard aGuard( + [&rWindowImpl]() + { + rWindowImpl.mnEventListenersIteratingCount--; + if (rWindowImpl.mnEventListenersIteratingCount == 0) + rWindowImpl.maEventListenersDeleted.clear(); + } + ); for ( Link<VclWindowEvent&,void>& rLink : aCopy ) { if (xWindow->IsDisposed()) break; // check this hasn't been removed in some re-enterancy scenario fdo#47368 - if( std::find(mpWindowImpl->maEventListeners.begin(), mpWindowImpl->maEventListeners.end(), rLink) != mpWindowImpl->maEventListeners.end() ) + if( rWindowImpl.maEventListenersDeleted.find(rLink) == rWindowImpl.maEventListenersDeleted.end() ) rLink.Call( aEvent ); } } @@ -279,6 +290,8 @@ void Window::RemoveEventListener( const Link<VclWindowEvent&,void>& rEventListen { auto& rListeners = mpWindowImpl->maEventListeners; rListeners.erase( std::remove(rListeners.begin(), rListeners.end(), rEventListener ), rListeners.end() ); + if (mpWindowImpl->mnEventListenersIteratingCount) + mpWindowImpl->maEventListenersDeleted.insert(rEventListener); } } diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index f245c475ee7b..d1c1ffe0dc49 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -615,6 +615,7 @@ WindowImpl::WindowImpl( WindowType nType ) mpNextOverlap = nullptr; // next overlap window of frame mpLastFocusWindow = nullptr; // window for focus restore mpDlgCtrlDownWindow = nullptr; // window for dialog control + mnEventListenersIteratingCount = 0; mnChildEventListenersIteratingCount = 0; mpUserData = nullptr; // user data mpCursor = nullptr; // cursor |