Kaydet (Commit) c2f318c6 authored tarafından Noel Grandin's avatar Noel Grandin Kaydeden (comit) Noel Grandin

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: 's avatarNoel Grandin <noel.grandin@collabora.co.uk>
üst 62775630
...@@ -24,34 +24,15 @@ inline sal_Int32 getRefCount( const rtl_uString* p ) ...@@ -24,34 +24,15 @@ inline sal_Int32 getRefCount( const rtl_uString* p )
return (p->refCount & 0x3FFFFFFF); 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 struct SharedStringPool::Impl
{ {
mutable osl::Mutex maMutex; mutable osl::Mutex maMutex;
StrHashType maStrPool; // set of upper-case, so we can share these as the value in the maStrMap
StrHashType maStrPoolUpper; std::unordered_set<OUString> maStrPoolUpper;
StrStoreType maStrStore; // map with rtl_uString* as key so we can avoid some ref-counting
std::unordered_map<OUString,rtl_uString*> maStrMap;
const CharClass& mrCharClass; const CharClass& mrCharClass;
explicit Impl( const CharClass& rCharClass ) : mrCharClass(rCharClass) {} explicit Impl( const CharClass& rCharClass ) : mrCharClass(rCharClass) {}
...@@ -68,72 +49,44 @@ SharedString SharedStringPool::intern( const OUString& rStr ) ...@@ -68,72 +49,44 @@ SharedString SharedStringPool::intern( const OUString& rStr )
{ {
osl::MutexGuard aGuard(&mpImpl->maMutex); osl::MutexGuard aGuard(&mpImpl->maMutex);
InsertResultType aRes = findOrInsert(mpImpl->maStrPool, rStr); auto mapIt = mpImpl->maStrMap.find(rStr);
if (mapIt == mpImpl->maStrMap.end())
rtl_uString* pOrig = aRes.first->pData;
if (!aRes.second)
{ {
// 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. // This is a new string insertion. Establish mapping to upper-case variant.
OUString aUpper = mpImpl->mrCharClass.uppercase(rStr); OUString aUpper = mpImpl->mrCharClass.uppercase(rStr);
aRes = findOrInsert(mpImpl->maStrPoolUpper, aUpper); auto insertResult = mpImpl->maStrPoolUpper.insert(aUpper);
assert(aRes.first != mpImpl->maStrPoolUpper.end()); mapIt = mpImpl->maStrMap.emplace_hint(mapIt, rStr, insertResult.first->pData);
}
mpImpl->maStrStore.emplace(pOrig, *aRes.first); return SharedString(mapIt->first.pData, mapIt->second);
return SharedString(pOrig, aRes.first->pData);
} }
void SharedStringPool::purge() void SharedStringPool::purge()
{ {
osl::MutexGuard aGuard(&mpImpl->maMutex); osl::MutexGuard aGuard(&mpImpl->maMutex);
StrHashType aNewStrPool; std::unordered_set<OUString> aNewStrPoolUpper;
StrHashType::iterator it = mpImpl->maStrPool.begin(), itEnd = mpImpl->maStrPool.end();
for (; it != itEnd; ++it)
{ {
const rtl_uString* p = it->pData; auto it = mpImpl->maStrMap.begin(), itEnd = mpImpl->maStrMap.end();
if (getRefCount(p) == 1) while (it != itEnd)
{ {
// Remove it from the upper string map. This should unref the const rtl_uString* p = it->first.pData;
// upper string linked to this original string. if (getRefCount(p) == 1)
mpImpl->maStrStore.erase(p); it = mpImpl->maStrMap.erase(it);
}
else else
{
// Still referenced outside the pool. Keep it. // Still referenced outside the pool. Keep it.
aNewStrPool.insert(*it); aNewStrPoolUpper.insert(it->second);
++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 size_t SharedStringPool::getCount() const
{ {
osl::MutexGuard aGuard(&mpImpl->maMutex); osl::MutexGuard aGuard(&mpImpl->maMutex);
return mpImpl->maStrPool.size(); return mpImpl->maStrMap.size();
} }
size_t SharedStringPool::getCountIgnoreCase() const size_t SharedStringPool::getCountIgnoreCase() const
......
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