[libcxx-commits] [libcxx] [libc++] Refactor the creation of the global and classic locales (PR #72581)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 16 14:42:30 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

<details>
<summary>Changes</summary>

The creation of the global and the classic locales was pretty twisty. This patch refactors how this is done to reduce the amount of indirections and prepare the terrain for a future where GCC implements the no_destroy attribute.

---
Full diff: https://github.com/llvm/llvm-project/pull/72581.diff


2 Files Affected:

- (modified) libcxx/include/__locale (+3) 
- (modified) libcxx/src/locale.cpp (+23-30) 


``````````diff
diff --git a/libcxx/include/__locale b/libcxx/include/__locale
index b1502dd71edadf6..0b0b94c99393b61 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -127,6 +127,9 @@ private:
     class __imp;
     __imp* __locale_;
 
+    template <class> friend struct no_destroy;
+    _LIBCPP_HIDE_FROM_ABI explicit locale(__imp* __loc) : __locale_(__loc) {}
+
     void __install_ctor(const locale&, facet*, long);
     static locale& __global();
     bool has_facet(id&) const;
diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index c37e091dcc4671b..6b1e5a6e4b494c4 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <__utility/unreachable.h>
 #include <algorithm>
 #include <clocale>
 #include <codecvt>
@@ -15,9 +14,11 @@
 #include <cstdlib>
 #include <cstring>
 #include <locale>
+#include <new>
 #include <string>
 #include <type_traits>
 #include <typeinfo>
+#include <utility>
 #include <vector>
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -154,8 +155,6 @@ class _LIBCPP_HIDDEN locale::__imp
         {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
     const locale::facet* use_facet(long id) const;
 
-    static const locale& make_classic();
-    static       locale& make_global();
 private:
     void install(facet* f, long id);
     template <class F> void install(F* f) {install(f, f->id.__get());}
@@ -538,37 +537,31 @@ locale::__imp::use_facet(long id) const
 
 // locale
 
-const locale&
-locale::__imp::make_classic()
-{
-    // only one thread can get in here and it only gets in once
-    alignas(locale) static std::byte buf[sizeof(locale)];
-    locale* c = reinterpret_cast<locale*>(&buf);
-    c->__locale_ = &make<__imp>(1u);
-    return *c;
-}
+// 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)...);
+    }
 
-const locale&
-locale::classic()
-{
-    static const locale& c = __imp::make_classic();
-    return c;
-}
+    T& get() { return *reinterpret_cast<T*>(&buf); }
+    T const& get() const { return *reinterpret_cast<T const*>(&buf); }
 
-locale&
-locale::__imp::make_global()
-{
-    // only one thread can get in here and it only gets in once
-    alignas(locale) static std::byte buf[sizeof(locale)];
-    auto *obj = ::new (&buf) locale(locale::classic());
-    return *obj;
+  private:
+    alignas(T) byte buf[sizeof(T)];
+};
+
+const locale& locale::classic() {
+    static const no_destroy<locale> c(&make<__imp>(1u));
+    return c.get();
 }
 
-locale&
-locale::__global()
-{
-    static locale& g = __imp::make_global();
-    return g;
+locale& locale::__global() {
+    static no_destroy<locale> g(locale::classic());
+    return g.get();
 }
 
 locale::locale() noexcept

``````````

</details>


https://github.com/llvm/llvm-project/pull/72581


More information about the libcxx-commits mailing list