[libcxx-commits] [libcxx] [libc++] Speed up classic locale (PR #72112)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Nov 23 11:30:30 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())
----------------
ldionne wrote:
Ok, I think this is definitely legal regardless, this is just a reinterpret cast like http://eel.is/c++draft/expr.reinterpret.cast#7 and we're not accessing the object as a `locale::__imp` before it is initialized. But even better, I can switch to a `union` in `__no_destroy` instead of an aligned `char` buffer and it makes the code cleaner and clearly correct.
https://github.com/llvm/llvm-project/pull/72112
More information about the libcxx-commits
mailing list