libstdc++-v3/ChangeLog: * src/c++20/format.cc (remove_ref): New deleter type. (move_to_front): New function. (lru_cache): New unique_ptr array. (__with_encoding_conversion): Use LRU cache. ---
Tested x86_64-linux. libstdc++-v3/src/c++20/format.cc | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/src/c++20/format.cc b/libstdc++-v3/src/c++20/format.cc index ee91c291d38..302664b673d 100644 --- a/libstdc++-v3/src/c++20/format.cc +++ b/libstdc++-v3/src/c++20/format.cc @@ -283,6 +283,22 @@ __get_encoding_facet(const locale& loc) return static_cast<const __encoding*>(loc._M_impl->_M_facets[id]); } +// Deleter for facets +struct remove_ref { + void operator()(locale::facet* p) const { p->_M_remove_reference(); } +}; +using Cache = array<unique_ptr<__encoding, remove_ref>, 3>; +Cache lru_cache; +mutex lru_cache_mx; + +void move_to_front(Cache::iterator it) +{ + while (it != lru_cache.begin()) + { + --it; + it->swap(it[1]); + } +} } // namespace locale @@ -301,9 +317,23 @@ __with_encoding_conversion(const locale& loc) || locenc == text_encoding::unknown) return loc; - auto facetp = std::make_unique<__encoding>(locenc); - locale loc2(loc, facetp.get()); // FIXME: PR libstdc++/113704 - facetp.release(); + lock_guard<mutex> lock(lru_cache_mx); + auto it = lru_cache.begin(), end = lru_cache.end(); + while (it != end && *it && (*it)->_M_enc != locenc) + ++it; + + if (it == end || *it == nullptr) // Cache miss. + { + if (it == end) // Cache is full, replace the last entry. + --it; + it->reset(new __encoding(locenc, 1)); + } + + // Move *it to the front of the cache. + move_to_front(it); + + locale loc2(loc, lru_cache[0].get()); // FIXME: PR libstdc++/113704 + // FIXME: Ideally we wouldn't need to reallocate this string again, // just don't delete[] it in the locale(locale, Facet*) constructor. if (const char* name = loc._M_impl->_M_names[0]) -- 2.47.0