Kaydet (Commit) a60b149e authored tarafından Eike Rathke's avatar Eike Rathke

reworked solution for i#118012 crash during deletion of rows

commit 16155fdc introduced a bottleneck
in area broadcasts with the change from
http://svn.apache.org/viewvc?view=revision&revision=1297916

That for each broadcast copied all areas in the affected slot(s) before
broadcasting, just in case that during Notify() an area would be removed
from the same slot invalidating the iterator, and attempted to find the
area again in the original set. For documents with lots of areas in a
slot and/or lots of slots that would be a major performance penalty.

Reworked such that to-be-erased area entries are marked and remembered
instead and cleaned up after iteration.

Change-Id: Ia485941746f435f8410d2084868263e84f25ffcb
üst 2316fe0d
This diff is collapsed.
...@@ -71,23 +71,31 @@ inline bool ScBroadcastArea::operator==( const ScBroadcastArea & rArea ) const ...@@ -71,23 +71,31 @@ inline bool ScBroadcastArea::operator==( const ScBroadcastArea & rArea ) const
//============================================================================= //=============================================================================
struct ScBroadcastAreaEntry
{
ScBroadcastArea* mpArea;
mutable bool mbErasure; ///< TRUE if marked for erasure in this set
ScBroadcastAreaEntry( ScBroadcastArea* p ) : mpArea( p), mbErasure( false) {}
};
struct ScBroadcastAreaHash struct ScBroadcastAreaHash
{ {
size_t operator()( const ScBroadcastArea* p ) const size_t operator()( const ScBroadcastAreaEntry& rEntry ) const
{ {
return p->GetRange().hashArea(); return rEntry.mpArea->GetRange().hashArea();
} }
}; };
struct ScBroadcastAreaEqual struct ScBroadcastAreaEqual
{ {
bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const bool operator()( const ScBroadcastAreaEntry& rEntry1, const ScBroadcastAreaEntry& rEntry2) const
{ {
return *p1 == *p2; return *rEntry1.mpArea == *rEntry2.mpArea;
} }
}; };
typedef ::boost::unordered_set< ScBroadcastArea*, ScBroadcastAreaHash, ScBroadcastAreaEqual > ScBroadcastAreas; typedef ::boost::unordered_set< ScBroadcastAreaEntry, ScBroadcastAreaHash, ScBroadcastAreaEqual > ScBroadcastAreas;
//============================================================================= //=============================================================================
...@@ -122,6 +130,7 @@ private: ...@@ -122,6 +130,7 @@ private:
mutable ScBroadcastArea aTmpSeekBroadcastArea; // for FindBroadcastArea() mutable ScBroadcastArea aTmpSeekBroadcastArea; // for FindBroadcastArea()
ScDocument* pDoc; ScDocument* pDoc;
ScBroadcastAreaSlotMachine* pBASM; ScBroadcastAreaSlotMachine* pBASM;
bool mbInBroadcastIteration;
ScBroadcastAreas::iterator FindBroadcastArea( const ScRange& rRange ) const; ScBroadcastAreas::iterator FindBroadcastArea( const ScRange& rRange ) const;
...@@ -135,6 +144,14 @@ private: ...@@ -135,6 +144,14 @@ private:
*/ */
bool CheckHardRecalcStateCondition() const; bool CheckHardRecalcStateCondition() const;
/** Finally erase all areas pushed as to-be-erased. */
void FinallyEraseAreas();
bool isMarkedErased( const ScBroadcastAreas::iterator& rIter )
{
return (*rIter).mbErasure;
}
public: public:
ScBroadcastAreaSlot( ScDocument* pDoc, ScBroadcastAreaSlot( ScDocument* pDoc,
ScBroadcastAreaSlotMachine* pBASM ); ScBroadcastAreaSlotMachine* pBASM );
...@@ -172,16 +189,27 @@ public: ...@@ -172,16 +189,27 @@ public:
void EndListeningArea( const ScRange& rRange, void EndListeningArea( const ScRange& rRange,
SvtListener* pListener, SvtListener* pListener,
ScBroadcastArea*& rpArea ); ScBroadcastArea*& rpArea );
sal_Bool AreaBroadcast( const ScHint& rHint ) const; sal_Bool AreaBroadcast( const ScHint& rHint );
/// @return sal_True if at least one broadcast occurred. /// @return sal_True if at least one broadcast occurred.
sal_Bool AreaBroadcastInRange( const ScRange& rRange, sal_Bool AreaBroadcastInRange( const ScRange& rRange,
const ScHint& rHint ) const; const ScHint& rHint );
void DelBroadcastAreasInRange( const ScRange& rRange ); void DelBroadcastAreasInRange( const ScRange& rRange );
void UpdateRemove( UpdateRefMode eUpdateRefMode, void UpdateRemove( UpdateRefMode eUpdateRefMode,
const ScRange& rRange, const ScRange& rRange,
SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
void UpdateRemoveArea( ScBroadcastArea* pArea ); void UpdateRemoveArea( ScBroadcastArea* pArea );
void UpdateInsert( ScBroadcastArea* pArea ); void UpdateInsert( ScBroadcastArea* pArea );
bool IsInBroadcastIteration() const { return mbInBroadcastIteration; }
/** Erase an area from set and delete it if last reference, or if
mbInBroadcastIteration is set push it to the vector of to-be-erased
areas instead.
Meant to be used internally and from ScBroadcastAreaSlotMachine only.
*/
void EraseArea( ScBroadcastAreas::iterator& rIter );
}; };
...@@ -229,14 +257,17 @@ private: ...@@ -229,14 +257,17 @@ private:
typedef ::std::map< SCTAB, TableSlots* > TableSlotsMap; typedef ::std::map< SCTAB, TableSlots* > TableSlotsMap;
typedef ::std::vector< ::std::pair< ScBroadcastAreaSlot*, ScBroadcastAreas::iterator > > AreasToBeErased;
private: private:
ScBroadcastAreasBulk aBulkBroadcastAreas; ScBroadcastAreasBulk aBulkBroadcastAreas;
TableSlotsMap aTableSlotsMap; TableSlotsMap aTableSlotsMap;
AreasToBeErased maAreasToBeErased;
SvtBroadcaster *pBCAlways; // for the RC_ALWAYS special range SvtBroadcaster *pBCAlways; // for the RC_ALWAYS special range
ScDocument *pDoc; ScDocument *pDoc;
ScBroadcastArea *pUpdateChain; ScBroadcastArea *pUpdateChain;
ScBroadcastArea *pEOUpdateChain; ScBroadcastArea *pEOUpdateChain;
sal_uLong nInBulkBroadcast; sal_uLong nInBulkBroadcast;
inline SCSIZE ComputeSlotOffset( const ScAddress& rAddress ) const; inline SCSIZE ComputeSlotOffset( const ScAddress& rAddress ) const;
void ComputeAreaPoints( const ScRange& rRange, void ComputeAreaPoints( const ScRange& rRange,
...@@ -267,6 +298,12 @@ public: ...@@ -267,6 +298,12 @@ public:
inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; } inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; }
inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; } inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; }
inline bool IsInBulkBroadcast() const { return nInBulkBroadcast > 0; } inline bool IsInBulkBroadcast() const { return nInBulkBroadcast > 0; }
// only for ScBroadcastAreaSlot
void PushAreaToBeErased( ScBroadcastAreaSlot* pSlot,
ScBroadcastAreas::iterator& rIter );
// only for ScBroadcastAreaSlot
void FinallyEraseAreas( ScBroadcastAreaSlot* pSlot );
}; };
......
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