Kaydet (Commit) 60e67b38 authored tarafından Noel Grandin's avatar Noel Grandin

fix O(n^2) in vcl event broadcasting tdf#90199

Change-Id: If3d7514364589058334369432cdcf4f7586c239d
üst 68f411fb
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <vcl/rendersettings.hxx> #include <vcl/rendersettings.hxx>
#include "vcleventlisteners.hxx" #include "vcleventlisteners.hxx"
#include <vector> #include <vector>
#include <set>
struct SalPaintEvent; struct SalPaintEvent;
struct ImplDelData; struct ImplDelData;
...@@ -231,6 +232,8 @@ public: ...@@ -231,6 +232,8 @@ public:
VclPtr<vcl::Window> mpDlgCtrlDownWindow; VclPtr<vcl::Window> mpDlgCtrlDownWindow;
std::vector<Link<VclWindowEvent&,void>> maEventListeners; std::vector<Link<VclWindowEvent&,void>> maEventListeners;
std::vector<Link<VclWindowEvent&,void>> maChildEventListeners; std::vector<Link<VclWindowEvent&,void>> maChildEventListeners;
int maChildEventListenersIteratingCount;
std::set<Link<VclWindowEvent&,void>> maChildEventListenersDeleted;
// The canvas interface for this VCL window. Is persistent after the first GetCanvas() call // The canvas interface for this VCL window. Is persistent after the first GetCanvas() call
css::uno::WeakReference< css::rendering::XCanvas > mxCanvas; css::uno::WeakReference< css::rendering::XCanvas > mxCanvas;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <com/sun/star/awt/MouseEvent.hpp> #include <com/sun/star/awt/MouseEvent.hpp>
#include <com/sun/star/awt/KeyModifier.hpp> #include <com/sun/star/awt/KeyModifier.hpp>
#include <com/sun/star/awt/MouseButton.hpp> #include <com/sun/star/awt/MouseButton.hpp>
#include <comphelper/scopeguard.hxx>
namespace vcl { namespace vcl {
...@@ -238,17 +239,26 @@ void Window::CallEventListeners( sal_uLong nEvent, void* pData ) ...@@ -238,17 +239,26 @@ void Window::CallEventListeners( sal_uLong nEvent, void* pData )
if ( aDelData.IsDead() ) if ( aDelData.IsDead() )
return; return;
auto& rChildListeners = pWindow->mpWindowImpl->maChildEventListeners; auto& rWindowImpl = *pWindow->mpWindowImpl;
if (!rChildListeners.empty()) if (!rWindowImpl.maChildEventListeners.empty())
{ {
// Copy the list, because this can be destroyed when calling a Link... // Copy the list, because this can be destroyed when calling a Link...
std::vector<Link<VclWindowEvent&,void>> aCopy( rChildListeners ); std::vector<Link<VclWindowEvent&,void>> aCopy( rWindowImpl.maChildEventListeners );
// we use an iterating counter/flag and a set of deleted Link's to avoid O(n^2) behaviour
rWindowImpl.maChildEventListenersIteratingCount++;
comphelper::ScopeGuard aGuard(
[&rWindowImpl]()
{
if (--rWindowImpl.maChildEventListenersIteratingCount == 0)
rWindowImpl.maChildEventListenersDeleted.clear();
}
);
for ( Link<VclWindowEvent&,void>& rLink : aCopy ) for ( Link<VclWindowEvent&,void>& rLink : aCopy )
{ {
if (aDelData.IsDead()) if (aDelData.IsDead())
return; return;
// check this hasn't been removed in some re-enterancy scenario fdo#47368 // Check this hasn't been removed in some re-enterancy scenario fdo#47368.
if( std::find(rChildListeners.begin(), rChildListeners.end(), rLink) != rChildListeners.end() ) if( rWindowImpl.maChildEventListenersDeleted.find(rLink) != rWindowImpl.maChildEventListenersDeleted.end() )
rLink.Call( aEvent ); rLink.Call( aEvent );
} }
} }
...@@ -292,6 +302,8 @@ void Window::RemoveChildEventListener( const Link<VclWindowEvent&,void>& rEventL ...@@ -292,6 +302,8 @@ void Window::RemoveChildEventListener( const Link<VclWindowEvent&,void>& rEventL
{ {
auto& rListeners = mpWindowImpl->maChildEventListeners; auto& rListeners = mpWindowImpl->maChildEventListeners;
rListeners.erase( std::remove(rListeners.begin(), rListeners.end(), rEventListener ), rListeners.end() ); rListeners.erase( std::remove(rListeners.begin(), rListeners.end(), rEventListener ), rListeners.end() );
if (mpWindowImpl->maChildEventListenersIteratingCount)
mpWindowImpl->maChildEventListenersDeleted.insert(rEventListener);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment