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