[Libreoffice-commits] core.git: Branch 'feature/perfwork5' - sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Nov 14 18:53:21 PST 2014


 sc/inc/address.hxx               |    3 +
 sc/source/core/data/bcaslot.cxx  |  100 +++++++++++++++++++++++++++++++++++++++
 sc/source/core/data/documen7.cxx |   62 +++++++++++++++++++++---
 sc/source/core/data/document.cxx |   10 +--
 sc/source/core/inc/bcaslot.hxx   |    2 
 sc/source/core/tool/address.cxx  |   15 +++++
 6 files changed, 178 insertions(+), 14 deletions(-)

New commits:
commit eee4f852e112acabbe1117caa88825497c13ec24
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Nov 14 21:51:39 2014 -0500

    Send broadcast range to the area broadcast slot machine.
    
    Rather than iterating through cells in the range and broadcasting by
    cells individually.  This way we can take advantage of the new group
    based area listeners and it's much faster this way.
    
    Change-Id: I8a4b49bce69d89b5b4698790befe4390871c755d

diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 7fcdee1..527cba2 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -563,6 +563,9 @@ public:
     SC_DLLPUBLIC void Justify();
     SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
     SC_DLLPUBLIC bool Intersects( const ScRange& rRange ) const;    // do two ranges intersect?
+
+    ScRange Union( const ScRange& rOther ) const;
+
     void PutInOrder();
     inline bool operator==( const ScRange& rRange ) const;
     inline bool operator!=( const ScRange& rRange ) const;
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index 9af7c19..ee6f17a 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -258,6 +258,83 @@ ScBroadcastAreas::const_iterator ScBroadcastAreaSlot::FindBroadcastArea(
     return aBroadcastAreaTbl.find( &aTmpSeekBroadcastArea);
 }
 
+namespace {
+
+void broadcastRangeByCell( SvtBroadcaster& rBC, const ScRange& rRange, sal_uLong nHint )
+{
+    ScHint aHint(nHint, ScAddress());
+    ScAddress& rPos = aHint.GetAddress();
+    for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+    {
+        rPos.SetTab(nTab);
+        for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+        {
+            rPos.SetCol(nCol);
+            for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
+            {
+                rPos.SetRow(nRow);
+                rBC.Broadcast(aHint);
+            }
+        }
+    }
+}
+
+}
+
+bool ScBroadcastAreaSlot::AreaBroadcast( const ScRange& rRange, sal_uLong nHint )
+{
+    if (aBroadcastAreaTbl.empty())
+        return false;
+
+    bool bInBroadcast = mbInBroadcastIteration;
+    mbInBroadcastIteration = true;
+    bool bIsBroadcasted = false;
+
+    mbHasErasedArea = false;
+
+    for (ScBroadcastAreas::const_iterator aIter( aBroadcastAreaTbl.begin()),
+            aIterEnd( aBroadcastAreaTbl.end()); aIter != aIterEnd; ++aIter )
+    {
+        if (mbHasErasedArea && isMarkedErased( aIter))
+            continue;
+
+        ScBroadcastArea* pArea = (*aIter).mpArea;
+        const ScRange& rAreaRange = pArea->GetRange();
+
+        // Take the union of the area range and the broadcast range.
+        ScRange aUnion = rAreaRange.Union(rRange);
+        if (!aUnion.IsValid())
+            continue;
+
+        if (pArea->IsGroupListening())
+        {
+            if (pBASM->IsInBulkBroadcast())
+            {
+                pBASM->InsertBulkGroupArea(pArea, aUnion);
+            }
+            else
+            {
+                broadcastRangeByCell(pArea->GetBroadcaster(), aUnion, nHint);
+                bIsBroadcasted = true;
+            }
+        }
+        else if (!pBASM->IsInBulkBroadcast() || pBASM->InsertBulkArea( pArea))
+        {
+            broadcastRangeByCell(pArea->GetBroadcaster(), aUnion, nHint);
+            bIsBroadcasted = true;
+        }
+    }
+
+    mbInBroadcastIteration = bInBroadcast;
+
+    // A Notify() during broadcast may call EndListeningArea() and thus dispose
+    // an area if it was the last listener, which would invalidate an iterator
+    // pointing to it, hence the real erase is done afterwards.
+    FinallyEraseAreas();
+
+    return bIsBroadcasted;
+}
+
 bool ScBroadcastAreaSlot::AreaBroadcast( const ScHint& rHint)
 {
     if (aBroadcastAreaTbl.empty())
@@ -758,6 +835,29 @@ void ScBroadcastAreaSlotMachine::EndListeningArea(
     }
 }
 
+bool ScBroadcastAreaSlotMachine::AreaBroadcast( const ScRange& rRange, sal_uLong nHint )
+{
+    bool bBroadcasted = false;
+    SCTAB nEndTab = rRange.aEnd.Tab();
+    for (TableSlotsMap::iterator iTab( aTableSlotsMap.lower_bound( rRange.aStart.Tab()));
+            iTab != aTableSlotsMap.end() && (*iTab).first <= nEndTab; ++iTab)
+    {
+        ScBroadcastAreaSlot** ppSlots = (*iTab).second->getSlots();
+        SCSIZE nStart, nEnd, nRowBreak;
+        ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+        SCSIZE nOff = nStart;
+        SCSIZE nBreak = nOff + nRowBreak;
+        ScBroadcastAreaSlot** pp = ppSlots + nOff;
+        while ( nOff <= nEnd )
+        {
+            if ( *pp )
+                bBroadcasted |= (*pp)->AreaBroadcast( rRange, nHint );
+            ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak);
+        }
+    }
+    return bBroadcasted;
+}
+
 bool ScBroadcastAreaSlotMachine::AreaBroadcast( const ScHint& rHint ) const
 {
     const ScAddress& rAddress = rHint.GetAddress();
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index 5ea4ce5..b7bdf30 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -100,24 +100,72 @@ void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
 {
     ClearFormulaContext();
 
-    ScBulkBroadcast aBulkBroadcast(pBASM);
+    if (!pBASM)
+        return;    // Clipboard or Undo
+
+    SCTAB nTab1 = rRange.aStart.Tab();
+    SCTAB nTab2 = rRange.aEnd.Tab();
+    SCROW nRow1 = rRange.aStart.Row();
+    SCROW nRow2 = rRange.aEnd.Row();
+    SCCOL nCol1 = rRange.aStart.Col();
+    SCCOL nCol2 = rRange.aEnd.Col();
 
     ScHint aHint(nHint, ScAddress());
     ScAddress& rPos = aHint.GetAddress();
-    for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+
+    if (!bHardRecalcState)
     {
-        rPos.SetTab(nTab);
-        for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+        ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
+        bool bIsBroadcasted = false;
+
+        for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
         {
-            rPos.SetCol(nCol);
-            for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
+            rPos.SetTab(nTab);
+            for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
             {
                 rPos.SetRow(nRow);
-                Broadcast(aHint);
+                for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+                {
+                    rPos.SetCol(nCol);
+                    SvtBroadcaster* pBC = GetBroadcaster(rPos);
+                    if (pBC)
+                    {
+                        pBC->Broadcast(aHint);
+                        bIsBroadcasted = true;
+                    }
+                }
+            }
+        }
+
+        if (pBASM->AreaBroadcast(rRange, nHint) || bIsBroadcasted)
+            TrackFormulas(nHint);
+    }
+
+    //  Repaint fuer bedingte Formate mit relativen Referenzen:
+    for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
+    {
+        ScTable* pTab = FetchTable(nTab);
+        if (!pTab)
+            continue;
+
+        ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
+        if (pCondFormList)
+        {
+            for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+            {
+                for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+                    pCondFormList->SourceChanged(ScAddress(nCol,nRow,nTab));
             }
         }
     }
 
+    for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
+    {
+        ScTable* pTab = FetchTable(nTab);
+        if (pTab)
+            pTab->SetStreamValid(false);
+    }
+
     BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
 }
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 57d2b26..8e55be7 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2590,7 +2590,6 @@ class BroadcastAction : public sc::ColumnSpanSet::ColumnAction
 {
     ScDocument& mrDoc;
     ScColumn* mpCol;
-    std::vector<SCROW> maRows;
 
 public:
     BroadcastAction( ScDocument& rDoc ) : mrDoc(rDoc), mpCol(NULL) {}
@@ -2606,12 +2605,9 @@ public:
             return;
 
         assert(mpCol);
-        maRows.clear();
-        maRows.reserve(nRow2-nRow1+1);
-        for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
-            maRows.push_back(nRow);
-
-        mpCol->BroadcastCells(maRows, SC_HINT_DATACHANGED);
+        ScRange aRange(mpCol->GetCol(), nRow1, mpCol->GetTab());
+        aRange.aEnd.SetRow(nRow2);
+        mrDoc.BroadcastCells(aRange, SC_HINT_DATACHANGED);
     };
 };
 
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx
index bf98908..27c87f8 100644
--- a/sc/source/core/inc/bcaslot.hxx
+++ b/sc/source/core/inc/bcaslot.hxx
@@ -211,6 +211,7 @@ public:
     void EndListeningArea(
         const ScRange& rRange, bool bGroupListening, SvtListener* pListener, ScBroadcastArea*& rpArea );
 
+    bool AreaBroadcast( const ScRange& rRange, sal_uLong nHint );
     bool                AreaBroadcast( const ScHint& rHint );
     /// @return true if at least one broadcast occurred.
     bool                AreaBroadcastInRange( const ScRange& rRange,
@@ -312,6 +313,7 @@ public:
     void EndListeningArea(
         const ScRange& rRange, bool bGroupListening, SvtListener* pListener );
 
+    bool AreaBroadcast( const ScRange& rRange, sal_uLong nHint );
     bool                AreaBroadcast( const ScHint& rHint ) const;
         // return: at least one broadcast occurred
     bool                AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint ) const;
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index c8c8f18..c03a190 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -1373,6 +1373,21 @@ bool ScRange::Intersects( const ScRange& rRange ) const
         );
 }
 
+ScRange ScRange::Union( const ScRange& rOther ) const
+{
+    SCCOL nCol1 = std::max(aStart.Col(), rOther.aStart.Col());
+    SCCOL nCol2 = std::min(aEnd.Col(), rOther.aEnd.Col());
+    SCROW nRow1 = std::max(aStart.Row(), rOther.aStart.Row());
+    SCROW nRow2 = std::min(aEnd.Row(), rOther.aEnd.Row());
+    SCTAB nTab1 = std::max(aStart.Tab(), rOther.aStart.Tab());
+    SCTAB nTab2 = std::min(aEnd.Tab(), rOther.aEnd.Tab());
+
+    if (nCol1 > nCol2 || nRow1 > nRow2 || nTab1 > nTab2)
+        return ScRange(ScAddress::INITIALIZE_INVALID);
+
+    return ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+}
+
 void ScRange::PutInOrder()
 {
     SCCOL nCol1 = aStart.Col(), nCol2 = aEnd.Col();


More information about the Libreoffice-commits mailing list