[libcxx-commits] [libcxx] [libc++] Speed up classic locale (PR #72112)
Dmitry Vyukov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Nov 23 08:36:02 PST 2023
================
@@ -537,55 +542,59 @@ locale::__imp::use_facet(long id) const
// locale
-// This class basically implements __attribute__((no_destroy)), which isn't supported
-// by GCC as of writing this.
-template <class T>
-struct __no_destroy {
- template <class... Args>
- explicit __no_destroy(Args&&... args) {
- T* obj = reinterpret_cast<T*>(&buf);
- new (obj) T(std::forward<Args>(args)...);
- }
-
- T& get() { return *reinterpret_cast<T*>(&buf); }
- T const& get() const { return *reinterpret_cast<T const*>(&buf); }
-
- private:
- alignas(T) byte buf[sizeof(T)];
-};
+// We don't do reference counting on the classic locale.
+// It's never destroyed anyway, but atomic reference counting may be very
+// expensive in parallel applications. The classic locale is used by default
+// in all streams. Note: if a new global locale is installed, then we lose
+// the benefit of no reference counting.
+__no_destroy<locale::__imp> locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic()
const locale& locale::classic() {
- static const __no_destroy<locale> c(__private_tag{}, &make<__imp>(1u));
- return c.get();
+ static const __no_destroy<locale> classic_locale(__private_tag{}, [] {
+ // executed exactly once on first initialization of `classic_locale`
+ locale::__imp::classic_locale_imp_.__emplace(1u);
+ return &locale::__imp::classic_locale_imp_.__get();
+ }());
+ return classic_locale.__get();
}
locale& locale::__global() {
- static __no_destroy<locale> g(locale::classic());
- return g.get();
+ static __no_destroy<locale> g(locale::classic());
+ return g.__get();
+}
+
+void locale::__imp::acquire() {
+ if (this != &locale::__imp::classic_locale_imp_.__get())
----------------
dvyukov wrote:
I suspect it may be possible. Even if classic() is transitively called from a global var ctor. There may be another global var that e.g. creates a stream with a non-classic locale.
We don't need the typed reference it this case. Can have a different method that returns just void*.
https://github.com/llvm/llvm-project/pull/72112
More information about the libcxx-commits
mailing list