summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/document.hxx5
-rw-r--r--sc/inc/interpretercontext.hxx4
-rw-r--r--sc/inc/rangecache.hxx5
-rw-r--r--sc/source/core/data/documen2.cxx49
-rw-r--r--sc/source/core/tool/interpretercontext.cxx12
-rw-r--r--sc/source/core/tool/rangecache.cxx4
6 files changed, 33 insertions, 46 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 7bd27c6b95fa..294d7deadecc 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -48,7 +48,7 @@
#include <cassert>
#include <memory>
#include <map>
-#include <mutex>
+#include <shared_mutex>
#include <optional>
#include <set>
#include <unordered_map>
@@ -471,7 +471,8 @@ private:
mutable ScInterpreterContext maInterpreterContext;
- std::mutex mScLookupMutex; // protection for thread-unsafe parts of handling ScLookup
+ std::shared_mutex mScLookupMutex; // protection for thread-unsafe parts of handling ScLookup
+ std::unique_ptr<ScSortedRangeCacheMap> mxScSortedRangeCache; // cache for unsorted lookups
static const sal_uInt16 nSrcVer; // file version (load/save)
sal_uInt16 nFormulaTrackCount;
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 9f424b1a4f42..4ecb1ed9de1a 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -23,7 +23,6 @@ class FormulaToken;
class ScDocument;
class SvNumberFormatter;
struct ScLookupCacheMap;
-struct ScSortedRangeCacheMap;
class ScInterpreter;
enum class SvNumFormatType : sal_Int16;
@@ -58,7 +57,6 @@ struct ScInterpreterContext
std::vector<formula::FormulaToken*> maTokens;
std::vector<DelayedSetNumberFormat> maDelayedSetNumberFormat;
std::unique_ptr<ScLookupCacheMap> mxScLookupCache; // cache for lookups like VLOOKUP and MATCH
- std::unique_ptr<ScSortedRangeCacheMap> mxScSortedRangeCache; // cache for unsorted lookups
// Allocation cache for "aConditions" array in ScInterpreter::IterateParameterIfs()
// This is populated/used only when formula-group threading is enabled.
std::vector<sal_uInt8> maConditions;
@@ -85,7 +83,6 @@ private:
void SetDocAndFormatter(const ScDocument& rDoc, SvNumberFormatter* pFormatter);
void Cleanup();
void ClearLookupCache();
- void ClearSortedRangeCache();
void initFormatTable();
SvNumberFormatter* mpFormatter;
mutable NFIndexAndFmtType maNFTypeCache;
@@ -139,7 +136,6 @@ class ScInterpreterContextPool
public:
// Only to be used to clear lookup cache in all pool elements
static void ClearLookupCaches();
- static void ClearSortedRangeCaches();
};
class ScThreadedInterpreterContextGetterGuard
diff --git a/sc/inc/rangecache.hxx b/sc/inc/rangecache.hxx
index fd5b12cbd8de..048d9b9ba046 100644
--- a/sc/inc/rangecache.hxx
+++ b/sc/inc/rangecache.hxx
@@ -45,7 +45,7 @@ class ScSortedRangeCache final : public SvtListener
public:
/// MUST be new'd because Notify() deletes.
ScSortedRangeCache(ScDocument* pDoc, const ScRange& rRange, const ScQueryParam& param,
- ScSortedRangeCacheMap& cacheMap, ScInterpreterContext* context);
+ ScInterpreterContext* context);
/// Remove from document structure and delete (!) cache on modify hint.
virtual void Notify(const SfxHint& rHint) override;
@@ -53,8 +53,6 @@ public:
const ScRange& getRange() const { return maRange; }
bool isDescending() const { return mDescending; }
- ScSortedRangeCacheMap& getCacheMap() const { return mCacheMap; }
-
enum class ValueType
{
Values,
@@ -102,7 +100,6 @@ private:
std::vector<size_t> mRowToIndex; // indexed by 'SCROW - maRange.aStart.Row()'
ScRange maRange;
ScDocument* mpDoc;
- ScSortedRangeCacheMap& mCacheMap;
bool mDescending;
ValueType mValues;
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index bcdbd9b586e9..ed090885ed3b 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -137,6 +137,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) :
nMacroInterpretLevel(0),
nInterpreterTableOpLevel(0),
maInterpreterContext( *this, nullptr ),
+ mxScSortedRangeCache(new ScSortedRangeCacheMap),
nFormulaTrackCount(0),
eHardRecalcState(HardRecalcState::OFF),
nVisibleTab( 0 ),
@@ -1198,25 +1199,31 @@ ScLookupCache & ScDocument::GetLookupCache( const ScRange & rRange, ScInterprete
ScSortedRangeCache& ScDocument::GetSortedRangeCache( const ScRange & rRange, const ScQueryParam& param,
ScInterpreterContext* pContext )
{
- ScSortedRangeCache* pCache = nullptr;
- if (!pContext->mxScSortedRangeCache)
- pContext->mxScSortedRangeCache.reset(new ScSortedRangeCacheMap);
- ScSortedRangeCacheMap* pCacheMap = pContext->mxScSortedRangeCache.get();
- // insert with temporary value to avoid doing two lookups
- auto [findIt, bInserted] = pCacheMap->aCacheMap.emplace(ScSortedRangeCache::makeHashKey(rRange, param), nullptr);
+ assert(mxScSortedRangeCache);
+ ScSortedRangeCache::HashKey key = ScSortedRangeCache::makeHashKey(rRange, param);
+ // This should be created just once for one range, and repeated calls should reuse it, even
+ // between threads (it doesn't make sense to use ScInterpreterContext and have all threads
+ // build their own copy of the same data). So first try read-only access, which should
+ // in most cases be enough.
+ {
+ std::shared_lock guard(mScLookupMutex);
+ auto findIt = mxScSortedRangeCache->aCacheMap.find(key);
+ if( findIt != mxScSortedRangeCache->aCacheMap.end())
+ return *findIt->second;
+ }
+ // Avoid recursive calls because of some cells in the range being dirty and triggering
+ // interpreting, which may call into this again. Threaded calculation makes sure
+ // no cells are dirty.
+ if(!IsThreadedGroupCalcInProgress())
+ InterpretCellsIfNeeded(rRange);
+ std::unique_lock guard(mScLookupMutex);
+ auto [findIt, bInserted] = mxScSortedRangeCache->aCacheMap.emplace(key, nullptr);
if (bInserted)
{
- findIt->second = std::make_unique<ScSortedRangeCache>(this, rRange, param, *pCacheMap, pContext);
- pCache = findIt->second.get();
- // The StartListeningArea() call is not thread-safe, as all threads
- // would access the same SvtBroadcaster.
- std::unique_lock guard( mScLookupMutex );
- StartListeningArea(rRange, false, pCache);
+ findIt->second = std::make_unique<ScSortedRangeCache>(this, rRange, param, pContext);
+ StartListeningArea(rRange, false, findIt->second.get());
}
- else
- pCache = (*findIt).second.get();
-
- return *pCache;
+ return *findIt->second;
}
void ScDocument::RemoveLookupCache( ScLookupCache & rCache )
@@ -1244,12 +1251,11 @@ void ScDocument::RemoveSortedRangeCache( ScSortedRangeCache & rCache )
// a result of user input or recalc). If it turns out this can be the case, locking is needed
// here and also in ScSortedRangeCache::Notify().
assert(!IsThreadedGroupCalcInProgress());
- auto & cacheMap = rCache.getCacheMap();
- auto it(cacheMap.aCacheMap.find(rCache.getHashKey()));
- if (it != cacheMap.aCacheMap.end())
+ auto it(mxScSortedRangeCache->aCacheMap.find(rCache.getHashKey()));
+ if (it != mxScSortedRangeCache->aCacheMap.end())
{
ScSortedRangeCache* pCache = (*it).second.release();
- cacheMap.aCacheMap.erase(it);
+ mxScSortedRangeCache->aCacheMap.erase(it);
assert(!IsThreadedGroupCalcInProgress()); // EndListeningArea() is not thread-safe
EndListeningArea(pCache->getRange(), false, &rCache);
return;
@@ -1261,10 +1267,9 @@ void ScDocument::ClearLookupCaches()
{
assert(!IsThreadedGroupCalcInProgress());
GetNonThreadedContext().mxScLookupCache.reset();
- GetNonThreadedContext().mxScSortedRangeCache.reset();
+ mxScSortedRangeCache->aCacheMap.clear();
// Clear lookup cache in all interpreter-contexts in the (threaded/non-threaded) pools.
ScInterpreterContextPool::ClearLookupCaches();
- ScInterpreterContextPool::ClearSortedRangeCaches();
}
bool ScDocument::IsCellInChangeTrack(const ScAddress &cell,Color *pColCellBorder)
diff --git a/sc/source/core/tool/interpretercontext.cxx b/sc/source/core/tool/interpretercontext.cxx
index c35b6a602fd2..0df4a8407c9c 100644
--- a/sc/source/core/tool/interpretercontext.cxx
+++ b/sc/source/core/tool/interpretercontext.cxx
@@ -64,7 +64,7 @@ void ScInterpreterContext::initFormatTable()
void ScInterpreterContext::Cleanup()
{
- // Do not disturb mxScLookupCache/mxScSortedRangeCache
+ // Do not disturb mxScLookupCache.
maConditions.clear();
maDelayedSetNumberFormat.clear();
ResetTokens();
@@ -72,8 +72,6 @@ void ScInterpreterContext::Cleanup()
void ScInterpreterContext::ClearLookupCache() { mxScLookupCache.reset(); }
-void ScInterpreterContext::ClearSortedRangeCache() { mxScSortedRangeCache.reset(); }
-
SvNumFormatType ScInterpreterContext::GetNumberFormatType(sal_uInt32 nFIndex) const
{
if (!mpDoc->IsThreadedGroupCalcInProgress())
@@ -167,14 +165,6 @@ void ScInterpreterContextPool::ClearLookupCaches()
rPtr->ClearLookupCache();
}
-void ScInterpreterContextPool::ClearSortedRangeCaches()
-{
- for (auto& rPtr : aThreadedInterpreterPool.maPool)
- rPtr->ClearSortedRangeCache();
- for (auto& rPtr : aNonThreadedInterpreterPool.maPool)
- rPtr->ClearSortedRangeCache();
-}
-
/* ScThreadedInterpreterContextGetterGuard */
ScThreadedInterpreterContextGetterGuard::ScThreadedInterpreterContextGetterGuard(
diff --git a/sc/source/core/tool/rangecache.cxx b/sc/source/core/tool/rangecache.cxx
index 79bebcfa8fe6..6a80ca786082 100644
--- a/sc/source/core/tool/rangecache.cxx
+++ b/sc/source/core/tool/rangecache.cxx
@@ -52,11 +52,9 @@ static ScSortedRangeCache::ValueType toValueType(const ScQueryParam& param)
}
ScSortedRangeCache::ScSortedRangeCache(ScDocument* pDoc, const ScRange& rRange,
- const ScQueryParam& param, ScSortedRangeCacheMap& cacheMap,
- ScInterpreterContext* context)
+ const ScQueryParam& param, ScInterpreterContext* context)
: maRange(rRange)
, mpDoc(pDoc)
- , mCacheMap(cacheMap)
, mDescending(needsDescending(param))
, mValues(toValueType(param))
{