SfxBroadcaster: fix STL conversion:
50cf7caee5
introduced a regression that
makes the smoketest fail on Windows (though strangely not on Linux),
because it removed the special handling of null pointers in the
SfxBroadcaster's listener array. It is evidently possible that
a listener may be either added or removed at the SfxBroadcaster
while that SfxBroadcaster is currently doing a Broadcast, hence
AddListener and RemoveListener must be careful not to make the in
progress iteration through the listener array fail.
svllo.dll!SfxBroadcaster::AddListener(SfxListener & rListener={...}) Line 114 + 0x43 bytes C++
svllo.dll!SfxListener::StartListening(SfxBroadcaster & rBroadcaster={...}, unsigned char bPreventDups=0) Line 89 C++
sfxlo.dll!SfxPrintHelper::initialize(const com::sun:⭐:uno::Sequence<com::sun:⭐:uno::Any> & aArguments={...}) Line 162 C++
sfxlo.dll!SfxBaseModel::impl_getPrintHelper() Line 3693 C++
sfxlo.dll!SfxBaseModel::Notify(SfxBroadcaster & rBC={...}, const SfxHint & rHint={...}) Line 2583 C++
svllo.dll!SfxBroadcaster::Broadcast(const SfxHint & rHint={...}) Line 56 + 0xb bytes C++
sfxlo.dll!SfxApplication::NotifyEvent(const SfxEventHint & rEventHint={...}, bool bSynchron=true) Line 918 C++
sfxlo.dll!SfxObjectShell::SetInitialized_Impl(const bool i_fromInitNew=true) Line 1146 + 0x37 bytes C++
sfxlo.dll!SfxObjectShell::FinishedLoading(unsigned short nFlags=3) Line 1302 C++
Change-Id: Id27d08faaa2472b57947960a92f19c44df55b72b
This commit is contained in:
parent
9d314ab71e
commit
6868efe203
2 changed files with 51 additions and 27 deletions
|
@ -33,7 +33,7 @@ class SVL_DLLPUBLIC SfxBroadcaster
|
|||
friend class SfxListener;
|
||||
typedef std::vector<SfxListener*> SfxListenerArr_Impl;
|
||||
|
||||
SfxListenerArr_Impl aListeners;
|
||||
SfxListenerArr_Impl m_Listeners;
|
||||
|
||||
private:
|
||||
void AddListener( SfxListener& rListener );
|
||||
|
@ -52,17 +52,14 @@ public:
|
|||
virtual ~SfxBroadcaster();
|
||||
|
||||
void Broadcast( const SfxHint &rHint );
|
||||
bool HasListeners() const
|
||||
{
|
||||
return !aListeners.empty();
|
||||
}
|
||||
bool HasListeners() const;
|
||||
size_t GetListenerCount() const
|
||||
{
|
||||
return aListeners.size();
|
||||
return m_Listeners.size();
|
||||
}
|
||||
SfxListener* GetListener( sal_uInt16 nNo ) const
|
||||
{
|
||||
return aListeners[nNo];
|
||||
return m_Listeners[nNo];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <tools/debug.hxx>
|
||||
#include <osl/diagnose.h>
|
||||
|
||||
#include <svl/hint.hxx>
|
||||
#include <svl/smplhint.hxx>
|
||||
|
@ -37,16 +37,17 @@ TYPEINIT0(SfxBroadcaster);
|
|||
//====================================================================
|
||||
// broadcast immediately
|
||||
|
||||
|
||||
void SfxBroadcaster::Broadcast( const SfxHint &rHint )
|
||||
{
|
||||
DBG_CHKTHIS(SfxBroadcaster, 0);
|
||||
|
||||
// notify all registered listeners exactly once
|
||||
for (size_t n = 0; n < aListeners.size(); ++n)
|
||||
for (size_t n = 0; n < m_Listeners.size(); ++n)
|
||||
{
|
||||
SfxListener* pListener = aListeners[n];
|
||||
pListener->Notify( *this, rHint );
|
||||
SfxListener *const pListener = m_Listeners[n];
|
||||
if (pListener) {
|
||||
pListener->Notify( *this, rHint );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,10 +60,12 @@ SfxBroadcaster::~SfxBroadcaster()
|
|||
Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
|
||||
|
||||
// remove all still registered listeners
|
||||
for (size_t nPos = 0; nPos < aListeners.size(); ++nPos)
|
||||
for (size_t nPos = 0; nPos < m_Listeners.size(); ++nPos)
|
||||
{
|
||||
SfxListener *pListener = aListeners[nPos];
|
||||
pListener->RemoveBroadcaster_Impl(*this);
|
||||
SfxListener *const pListener = m_Listeners[nPos];
|
||||
if (pListener) {
|
||||
pListener->RemoveBroadcaster_Impl(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,10 +87,12 @@ SfxBroadcaster::SfxBroadcaster( const SfxBroadcaster &rBC )
|
|||
{
|
||||
DBG_CTOR(SfxBroadcaster, 0);
|
||||
|
||||
for (size_t n = 0; n < rBC.aListeners.size(); ++n)
|
||||
for (size_t n = 0; n < rBC.m_Listeners.size(); ++n)
|
||||
{
|
||||
SfxListener *pListener = rBC.aListeners[n];
|
||||
pListener->StartListening( *this );
|
||||
SfxListener *const pListener = rBC.m_Listeners[n];
|
||||
if (pListener) {
|
||||
pListener->StartListening( *this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +104,15 @@ void SfxBroadcaster::AddListener( SfxListener& rListener )
|
|||
{
|
||||
DBG_CHKTHIS(SfxBroadcaster, 0);
|
||||
|
||||
aListeners.push_back(&rListener);
|
||||
for (size_t i = 0; i < m_Listeners.size(); ++i)
|
||||
{
|
||||
if (!m_Listeners[i]) // removed by RemoveListener?
|
||||
{
|
||||
m_Listeners[i] = &rListener;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_Listeners.push_back(&rListener);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -117,10 +130,12 @@ void SfxBroadcaster::ListenersGone()
|
|||
|
||||
void SfxBroadcaster::Forward(SfxBroadcaster& rBC, const SfxHint& rHint)
|
||||
{
|
||||
for (size_t i = 0; i < aListeners.size(); ++i)
|
||||
for (size_t i = 0; i < m_Listeners.size(); ++i)
|
||||
{
|
||||
SfxListener *pListener = aListeners[i];
|
||||
pListener->Notify( rBC, rHint );
|
||||
SfxListener *const pListener = m_Listeners[i];
|
||||
if (pListener) {
|
||||
pListener->Notify( rBC, rHint );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,14 +146,26 @@ void SfxBroadcaster::Forward(SfxBroadcaster& rBC, const SfxHint& rHint)
|
|||
void SfxBroadcaster::RemoveListener( SfxListener& rListener )
|
||||
{
|
||||
{DBG_CHKTHIS(SfxBroadcaster, 0);}
|
||||
const SfxListener *pListener = &rListener;
|
||||
|
||||
SfxListenerArr_Impl::iterator aIter = std::remove(aListeners.begin(), aListeners.end(), pListener);
|
||||
DBG_ASSERT( aIter != aListeners.end(), "RemoveListener: Listener unknown" );
|
||||
aListeners.erase(aIter, aListeners.end());
|
||||
SfxListenerArr_Impl::iterator aIter = std::find(
|
||||
m_Listeners.begin(), m_Listeners.end(), &rListener);
|
||||
assert(aIter != m_Listeners.end()); // "RemoveListener: Listener unknown"
|
||||
// DO NOT erase the listener, set the pointer to 0
|
||||
// because the current continuation may contain this->Broadcast
|
||||
*aIter = 0;
|
||||
|
||||
if ( !HasListeners() )
|
||||
ListenersGone();
|
||||
}
|
||||
|
||||
bool SfxBroadcaster::HasListeners() const
|
||||
{
|
||||
for (size_t i = 0; i < m_Listeners.size(); ++i)
|
||||
{
|
||||
if (m_Listeners[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
Loading…
Reference in a new issue