From bc17ec1f2cb6d043b6b4fdb4a0116ad496a1ae81 Mon Sep 17 00:00:00 2001 From: Edin Muharemagic Date: Tue, 26 Jun 2012 10:12:11 -0400 Subject: [PATCH] Unicodelib RuleBasedCollator handle caching unicodelib.UnicodeLocaleEditDistanceWithinRadius() and unicodelib.UnicodeLocaleEditDistance() create a RuleBasedCollator instance on every invovation. Sharing the same RuleBasedCollator instance doubles performance of these 2 unicodelib functions. --- plugins/unicodelib/unicodelib.cpp | 84 ++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/plugins/unicodelib/unicodelib.cpp b/plugins/unicodelib/unicodelib.cpp index c04cb161d3f..82a433342c2 100644 --- a/plugins/unicodelib/unicodelib.cpp +++ b/plugins/unicodelib/unicodelib.cpp @@ -30,7 +30,7 @@ #include "unicode/rbbi.h" #include "../stringlib/wildmatch.tpp" -#define UNICODELIB_VERSION "UNICODELIB 1.1.05" +#define UNICODELIB_VERSION "UNICODELIB 1.1.06" UChar32 const u32comma = ','; UChar32 const u32space = ' '; @@ -91,6 +91,7 @@ static const char * compatibleVersions[] = { "UNICODELIB 1.1.02", "UNICODELIB 1.1.03", "UNICODELIB 1.1.04", + "UNICODELIB 1.1.05", NULL }; UNICODELIB_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb) @@ -271,6 +272,77 @@ inline UChar u16toupper(UChar c) static icu::Transliterator* deAccenter = NULL; static CriticalSection accenterCrit; +#define MAXAVAILABLELOCALES 256 + +struct LocaleRec +{ + RuleBasedCollator * rbc; + CSingletonLock slock; + int hash; +}; + +interface IRbcCache : public IInterface +{ +public: + virtual RuleBasedCollator* getRbc(char const * localename) = 0; +}; + +class CRbcCache : public CInterface, implements IRbcCache +{ +private: + LocaleRec m_locale[MAXAVAILABLELOCALES]; + +public: + IMPLEMENT_IINTERFACE; + + CRbcCache() + { + for(int i = 0; i < MAXAVAILABLELOCALES; i++) + { + m_locale[i].rbc = NULL; + m_locale[i].hash = 0; + } + }; + + RuleBasedCollator *getRbc(char const * localename) + { + UErrorCode status = U_ZERO_ERROR; + Locale locale(localename); + int hc = locale.hashCode(); + int lIndex = 0; // default to the rbc associated with the first locale requested by an app + for(int i = 0; i < MAXAVAILABLELOCALES; i++) + { + if ((hc != m_locale[i].hash) && (m_locale[i].hash != 0) )continue; + if (m_locale[i].hash == 0) m_locale[i].hash = hc; + lIndex = i; + break; + } + + if (m_locale[lIndex].slock.lock()) { + if (!m_locale[lIndex].rbc) + m_locale[lIndex].rbc = (RuleBasedCollator*)RuleBasedCollator::createInstance(locale, status); + m_locale[lIndex].slock.unlock(); + } + return m_locale[lIndex].rbc; + } + + ~CRbcCache() + { + for(int i = 0; i < MAXAVAILABLELOCALES; i++) + { + if (m_locale[i].hash != 0) delete m_locale[i].rbc; + } + } +}; + +IRbcCache* getRbcCache() +{ + static Owned rbccache; + if(!rbccache) + rbccache.setown(new CRbcCache()); + return rbccache.get(); +} + inline unsigned char min3(unsigned char a, unsigned char b, unsigned char c) { unsigned char min = (agetRbc(localename); + rbc->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status); UnicodeString uLeft(left, leftLen); @@ -1032,9 +1104,9 @@ UNICODELIB_API unsigned UNICODELIB_CALL ulUnicodeLocaleEditDistance(unsigned lef UNICODELIB_API bool UNICODELIB_CALL ulUnicodeLocaleEditDistanceWithinRadius(unsigned leftLen, UChar const * left, unsigned rightLen, UChar const * right, unsigned radius, char const * localename) { UErrorCode status = U_ZERO_ERROR; - Locale locale(localename); + IRbcCache *rbcCache = getRbcCache(); + RuleBasedCollator *rbc = rbcCache->getRbc(localename); - RuleBasedCollator* rbc = (RuleBasedCollator*)RuleBasedCollator::createInstance(locale, status); rbc->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status); UnicodeString uLeft(left, leftLen);