summaryrefslogtreecommitdiff
path: root/svl/source/notify/lstner.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svl/source/notify/lstner.cxx')
-rw-r--r--svl/source/notify/lstner.cxx47
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
}