summaryrefslogtreecommitdiff
path: root/svl
diff options
context:
space:
mode:
authorNoel Grandin <noelgrandin@gmail.com>2018-08-07 17:01:29 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2018-08-08 09:30:15 +0200
commitc2f318c6e57bf7b5d3b3c1cb19846e5261080daa (patch)
tree4f7f55fef239805da1d82f7162670dee5e8014c3 /svl
parent62775630afc80d1da0dc345e8ec10123a8e05463 (diff)
improve SharedStringPool
we don't need two sets, we can simplify the logic and let the key in the map perform the same function that one of the sets was performing. Change-Id: If042fd0d1483fb603967164c429a085a4f0b31eb Reviewed-on: https://gerrit.libreoffice.org/58692 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'svl')
-rw-r--r--svl/source/misc/sharedstringpool.cxx97
1 files changed, 25 insertions, 72 deletions
diff --git a/svl/source/misc/sharedstringpool.cxx b/svl/source/misc/sharedstringpool.cxx
index af1d80ef65d0..406f643f0fd6 100644
--- a/svl/source/misc/sharedstringpool.cxx
+++ b/svl/source/misc/sharedstringpool.cxx
@@ -24,34 +24,15 @@ inline sal_Int32 getRefCount( const rtl_uString* p )
return (p->refCount & 0x3FFFFFFF);
}
-typedef std::unordered_set<OUString> StrHashType;
-typedef std::pair<StrHashType::iterator, bool> InsertResultType;
-typedef std::unordered_map<const rtl_uString*, OUString> StrStoreType;
-
-InsertResultType findOrInsert( StrHashType& rPool, const OUString& rStr )
-{
- StrHashType::iterator it = rPool.find(rStr);
- bool bInserted = false;
- if (it == rPool.end())
- {
- // Not yet in the pool.
- std::pair<StrHashType::iterator, bool> r = rPool.insert(rStr);
- assert(r.second);
- it = r.first;
- bInserted = true;
- }
-
- return InsertResultType(it, bInserted);
-}
-
}
struct SharedStringPool::Impl
{
mutable osl::Mutex maMutex;
- StrHashType maStrPool;
- StrHashType maStrPoolUpper;
- StrStoreType maStrStore;
+ // set of upper-case, so we can share these as the value in the maStrMap
+ std::unordered_set<OUString> maStrPoolUpper;
+ // map with rtl_uString* as key so we can avoid some ref-counting
+ std::unordered_map<OUString,rtl_uString*> maStrMap;
const CharClass& mrCharClass;
explicit Impl( const CharClass& rCharClass ) : mrCharClass(rCharClass) {}
@@ -68,72 +49,44 @@ SharedString SharedStringPool::intern( const OUString& rStr )
{
osl::MutexGuard aGuard(&mpImpl->maMutex);
- InsertResultType aRes = findOrInsert(mpImpl->maStrPool, rStr);
-
- rtl_uString* pOrig = aRes.first->pData;
-
- if (!aRes.second)
+ auto mapIt = mpImpl->maStrMap.find(rStr);
+ if (mapIt == mpImpl->maStrMap.end())
{
- // No new string has been inserted. Return the existing string in the pool.
- StrStoreType::const_iterator it = mpImpl->maStrStore.find(pOrig);
- assert(it != mpImpl->maStrStore.end());
-
- rtl_uString* pUpper = it->second.pData;
- return SharedString(pOrig, pUpper);
+ // This is a new string insertion. Establish mapping to upper-case variant.
+ OUString aUpper = mpImpl->mrCharClass.uppercase(rStr);
+ auto insertResult = mpImpl->maStrPoolUpper.insert(aUpper);
+ mapIt = mpImpl->maStrMap.emplace_hint(mapIt, rStr, insertResult.first->pData);
}
-
- // This is a new string insertion. Establish mapping to upper-case variant.
-
- OUString aUpper = mpImpl->mrCharClass.uppercase(rStr);
- aRes = findOrInsert(mpImpl->maStrPoolUpper, aUpper);
- assert(aRes.first != mpImpl->maStrPoolUpper.end());
-
- mpImpl->maStrStore.emplace(pOrig, *aRes.first);
-
- return SharedString(pOrig, aRes.first->pData);
+ return SharedString(mapIt->first.pData, mapIt->second);
}
void SharedStringPool::purge()
{
osl::MutexGuard aGuard(&mpImpl->maMutex);
- StrHashType aNewStrPool;
- StrHashType::iterator it = mpImpl->maStrPool.begin(), itEnd = mpImpl->maStrPool.end();
- for (; it != itEnd; ++it)
+ std::unordered_set<OUString> aNewStrPoolUpper;
{
- const rtl_uString* p = it->pData;
- if (getRefCount(p) == 1)
+ auto it = mpImpl->maStrMap.begin(), itEnd = mpImpl->maStrMap.end();
+ while (it != itEnd)
{
- // Remove it from the upper string map. This should unref the
- // upper string linked to this original string.
- mpImpl->maStrStore.erase(p);
+ const rtl_uString* p = it->first.pData;
+ if (getRefCount(p) == 1)
+ it = mpImpl->maStrMap.erase(it);
+ else
+ {
+ // Still referenced outside the pool. Keep it.
+ aNewStrPoolUpper.insert(it->second);
+ ++it;
+ }
}
- else
- // Still referenced outside the pool. Keep it.
- aNewStrPool.insert(*it);
- }
-
- mpImpl->maStrPool.swap(aNewStrPool);
-
- aNewStrPool.clear(); // for re-use.
-
- // Purge the upper string pool as well.
- it = mpImpl->maStrPoolUpper.begin();
- itEnd = mpImpl->maStrPoolUpper.end();
- for (; it != itEnd; ++it)
- {
- const rtl_uString* p = it->pData;
- if (getRefCount(p) > 1)
- aNewStrPool.insert(*it);
}
-
- mpImpl->maStrPoolUpper.swap(aNewStrPool);
+ mpImpl->maStrPoolUpper = std::move(aNewStrPoolUpper);
}
size_t SharedStringPool::getCount() const
{
osl::MutexGuard aGuard(&mpImpl->maMutex);
- return mpImpl->maStrPool.size();
+ return mpImpl->maStrMap.size();
}
size_t SharedStringPool::getCountIgnoreCase() const