diff options
-rw-r--r-- | svl/source/notify/SfxBroadcaster.cxx | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/svl/source/notify/SfxBroadcaster.cxx b/svl/source/notify/SfxBroadcaster.cxx index f4e00e860333..2e312a80ce85 100644 --- a/svl/source/notify/SfxBroadcaster.cxx +++ b/svl/source/notify/SfxBroadcaster.cxx @@ -124,13 +124,32 @@ void SfxBroadcaster::Forward(SfxBroadcaster& rBC, const SfxHint& rHint) void SfxBroadcaster::RemoveListener( SfxListener& rListener ) { DBG_TESTSOLARMUTEX(); - SfxListenerArr_Impl::iterator aIter = std::find( - mpImpl->m_Listeners.begin(), mpImpl->m_Listeners.end(), &rListener); - assert(aIter != mpImpl->m_Listeners.end()); // "RemoveListener: Listener unknown" + + // First, check the slots either side of the last removed slot, makes a significant + // difference when the list is large. + int positionOfRemovedElement = -1; + if (!mpImpl->m_RemovedPositions.empty()) + { + auto i = mpImpl->m_RemovedPositions.back(); + if (i < mpImpl->m_Listeners.size() - 2 && mpImpl->m_Listeners[i+1] == &rListener) + { + positionOfRemovedElement = i + 1; + } + else if (i > 0 && mpImpl->m_Listeners[i-1] == &rListener) + { + positionOfRemovedElement = i-1; + } + } + // then scan the whole list if we didn't find it + if (positionOfRemovedElement == -1) + { + SfxListenerArr_Impl::iterator aIter = std::find( + mpImpl->m_Listeners.begin(), mpImpl->m_Listeners.end(), &rListener); + positionOfRemovedElement = std::distance(mpImpl->m_Listeners.begin(), aIter); + } // DO NOT erase the listener, set the pointer to 0 // because the current continuation may contain this->Broadcast - *aIter = nullptr; - size_t positionOfRemovedElement = std::distance(mpImpl->m_Listeners.begin(), aIter); + mpImpl->m_Listeners[positionOfRemovedElement] = nullptr; mpImpl->m_RemovedPositions.push_back(positionOfRemovedElement); } |