Kaydet (Commit) c8b62432 authored tarafından Jan Holesovsky's avatar Jan Holesovsky

Don't call EndListening() on already destructed listeners.

Change-Id: I9bda35f2246de9d37077dda33c710b89ee008e5a
üst 5527a867
...@@ -70,10 +70,15 @@ public: ...@@ -70,10 +70,15 @@ public:
* themselves from the broadcaster - the broadcaster will not broadcast * themselves from the broadcaster - the broadcaster will not broadcast
* anything after the PrepareForDesctruction() call anyway. * anything after the PrepareForDesctruction() call anyway.
*/ */
void PrepareForDestruction() { mbAboutToDie = true; } void PrepareForDestruction();
private: private:
ListenersType maListeners; ListenersType maListeners;
/// When the broadcaster is about to die, collect listeners that asked for removal.
ListenersType maDestructedListeners;
/// Indicate that this broadcaster will be destructed (we indicate this on all ScColumn's broadcasters during the ScTable destruction, eg.)
bool mbAboutToDie:1; bool mbAboutToDie:1;
bool mbDisposing:1; bool mbDisposing:1;
bool mbNormalized:1; bool mbNormalized:1;
......
...@@ -35,18 +35,6 @@ public: ...@@ -35,18 +35,6 @@ public:
} }
}; };
class EndListeningHandler : std::unary_function<SvtListener*, void>
{
SvtBroadcaster& mrBC;
public:
EndListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {}
void operator() ( SvtListener* p )
{
p->EndListening(mrBC);
}
};
class NotifyHandler : std::unary_function<SvtListener*, void> class NotifyHandler : std::unary_function<SvtListener*, void>
{ {
SvtBroadcaster& mrBC; SvtBroadcaster& mrBC;
...@@ -81,9 +69,15 @@ void SvtBroadcaster::Add( SvtListener* p ) ...@@ -81,9 +69,15 @@ void SvtBroadcaster::Add( SvtListener* p )
void SvtBroadcaster::Remove( SvtListener* p ) void SvtBroadcaster::Remove( SvtListener* p )
{ {
if (mbAboutToDie || mbDisposing) if (mbDisposing)
return; return;
if (mbAboutToDie)
{
maDestructedListeners.push_back(p);
return;
}
Normalize(); Normalize();
std::pair<ListenersType::iterator,ListenersType::iterator> r = std::pair<ListenersType::iterator,ListenersType::iterator> r =
std::equal_range(maListeners.begin(), maListeners.end(), p); std::equal_range(maListeners.begin(), maListeners.end(), p);
...@@ -107,8 +101,27 @@ SvtBroadcaster::~SvtBroadcaster() ...@@ -107,8 +101,27 @@ SvtBroadcaster::~SvtBroadcaster()
mbDisposing = true; mbDisposing = true;
Broadcast( SfxSimpleHint(SFX_HINT_DYING) ); Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
// unregister all listeners. // normalize the list of listeners than already asked for destruction
std::for_each(maListeners.begin(), maListeners.end(), EndListeningHandler(*this)); std::sort(maDestructedListeners.begin(), maDestructedListeners.end());
ListenersType::iterator itUniqueEnd = std::unique(maDestructedListeners.begin(), maDestructedListeners.end());
maDestructedListeners.erase(itUniqueEnd, maDestructedListeners.end());
// and the list of registered listeners too
Normalize();
// now when both lists are sorted, we can linearly unregister all
// listeners, with the exception of those that already asked to be removed
// during their own destruction
ListenersType::iterator dest(maDestructedListeners.begin());
for (ListenersType::iterator it(maListeners.begin()); it < maListeners.end(); ++it)
{
// skip the destructed ones
while (dest != maDestructedListeners.end() && (*dest < *it))
++dest;
if (dest == maDestructedListeners.end() || *dest != *it)
(*it)->EndListening(*this);
}
} }
void SvtBroadcaster::Broadcast( const SfxHint &rHint ) void SvtBroadcaster::Broadcast( const SfxHint &rHint )
...@@ -133,4 +146,10 @@ bool SvtBroadcaster::HasListeners() const ...@@ -133,4 +146,10 @@ bool SvtBroadcaster::HasListeners() const
return !maListeners.empty(); return !maListeners.empty();
} }
void SvtBroadcaster::PrepareForDestruction()
{
mbAboutToDie = true;
maDestructedListeners.reserve(maListeners.size());
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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