Skip to content

Commit 0c5f715

Browse files
committed
Don't recreate PluralFormsCalculator needlessly
Add caching to PluralFormsExpr::calc() so that plural expressions are only parsed once and the created calculator objects are reused. This is MT safe, because the calculator, once constructed, is const and doesn't modify its internal state.
1 parent 68a3699 commit 0c5f715

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

src/language.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -803,12 +803,32 @@ int PluralFormsExpr::nplurals() const
803803

804804
std::shared_ptr<PluralFormsCalculator> PluralFormsExpr::calc() const
805805
{
806-
auto self = const_cast<PluralFormsExpr*>(this);
807806
if (m_calcCreated)
808807
return m_calc;
808+
809809
if (!m_expr.empty())
810-
self->m_calc = PluralFormsCalculator::make(m_expr.c_str());
811-
self->m_calcCreated = true;
810+
{
811+
// There's typically only a few expressions used at runtime. Cache them to
812+
// avoid unnecessary re-creation.
813+
static std::unordered_map<std::string, std::shared_ptr<PluralFormsCalculator>> cache;
814+
static std::mutex cacheMutex;
815+
816+
std::lock_guard<std::mutex> lock(cacheMutex);
817+
818+
auto it = cache.find(m_expr);
819+
if (it != cache.end())
820+
{
821+
m_calc = it->second;
822+
}
823+
else
824+
{
825+
// Create new calculator and cache it
826+
m_calc = PluralFormsCalculator::make(m_expr.c_str());
827+
cache[m_expr] = m_calc;
828+
}
829+
}
830+
831+
m_calcCreated = true;
812832
return m_calc;
813833
}
814834

src/language.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ class PluralFormsExpr
235235

236236
std::string m_expr;
237237
mutable int m_nplurals;
238-
bool m_calcCreated;
239-
std::shared_ptr<PluralFormsCalculator> m_calc;
238+
mutable bool m_calcCreated;
239+
mutable std::shared_ptr<PluralFormsCalculator> m_calc;
240240
};
241241

242242
#endif // Poedit_language_h

0 commit comments

Comments
 (0)