diff options
Diffstat (limited to 'svl/source/notify/lstner.cxx')
-rw-r--r-- | svl/source/notify/lstner.cxx | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/svl/source/notify/lstner.cxx b/svl/source/notify/lstner.cxx index 4279e12f4a5c..0b3d2e9a3af5 100644 --- a/svl/source/notify/lstner.cxx +++ b/svl/source/notify/lstner.cxx @@ -21,17 +21,22 @@ #include <svl/hint.hxx> #include <svl/SfxBroadcaster.hxx> +#include <sal/backtrace.hxx> #include <algorithm> #include <cassert> #include <deque> - +#include <memory> +#include <map> typedef std::deque<SfxBroadcaster*> SfxBroadcasterArr_Impl; struct SfxListener::Impl { SfxBroadcasterArr_Impl maBCs; +#ifdef DBG_UTIL + std::map<SfxBroadcaster*, std::unique_ptr<BacktraceState>> maCallStacks; +#endif }; // simple ctor of class SfxListener @@ -68,27 +73,47 @@ void SfxListener::RemoveBroadcaster_Impl( SfxBroadcaster& rBroadcaster ) auto it = std::find( mpImpl->maBCs.begin(), mpImpl->maBCs.end(), &rBroadcaster ); if (it != mpImpl->maBCs.end()) { mpImpl->maBCs.erase( it ); +#ifdef DBG_UTIL + mpImpl->maCallStacks.erase( &rBroadcaster ); +#endif } } -// registers a specific SfxBroadcaster -void SfxListener::StartListening( SfxBroadcaster& rBroadcaster, bool bPreventDups ) +/** + Registers a specific SfxBroadcaster. + + Some code uses duplicates as a kind of ref-counting thing i.e. they add and remove listeners + on different code paths, and they only really stop listening when the last EndListening() is called. +*/ +void SfxListener::StartListening( SfxBroadcaster& rBroadcaster, bool bPreventDuplicates ) { - if ( !bPreventDups || !IsListening( rBroadcaster ) ) + bool bListeningAlready = IsListening( rBroadcaster ); + +#ifdef DBG_UTIL + if (bListeningAlready && !bPreventDuplicates) + { + auto f = mpImpl->maCallStacks.find( &rBroadcaster ); + SAL_INFO("svl", "previous StartListening call came from: " << sal_backtrace_to_string(f->second.get())); + } +#endif + assert(!(bListeningAlready && !bPreventDuplicates) && "duplicate listener, try building with DBG_UTIL to find the other insert site."); + + if ( !bListeningAlready || !bPreventDuplicates ) { rBroadcaster.AddListener(*this); mpImpl->maBCs.push_back( &rBroadcaster ); - +#ifdef DBG_UTIL + mpImpl->maCallStacks.emplace( &rBroadcaster, sal_backtrace_get(10) ); +#endif assert(IsListening(rBroadcaster) && "StartListening failed"); } } - // unregisters a specific SfxBroadcaster -void SfxListener::EndListening( SfxBroadcaster& rBroadcaster, bool bAllDups ) +void SfxListener::EndListening( SfxBroadcaster& rBroadcaster, bool bRemoveAllDuplicates ) { SfxBroadcasterArr_Impl::iterator beginIt = mpImpl->maBCs.begin(); do @@ -100,8 +125,11 @@ void SfxListener::EndListening( SfxBroadcaster& rBroadcaster, bool bAllDups ) } rBroadcaster.RemoveListener(*this); beginIt = mpImpl->maBCs.erase( it ); +#ifdef DBG_UTIL + mpImpl->maCallStacks.erase( &rBroadcaster ); +#endif } - while ( bAllDups ); + while ( bRemoveAllDuplicates ); } @@ -116,6 +144,9 @@ void SfxListener::EndListeningAll() pBC->RemoveListener(*this); mpImpl->maBCs.pop_front(); } +#ifdef DBG_UTIL + mpImpl->maCallStacks.clear(); +#endif } |