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

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 23 07:29:02 PST 2023


Author: Louis Dionne
Date: 2023-11-23T10:28:57-05:00
New Revision: 026776fb60e52be04ea26d3d1d371d9efcb6ae3b

URL: https://github.com/llvm/llvm-project/commit/026776fb60e52be04ea26d3d1d371d9efcb6ae3b
DIFF: https://github.com/llvm/llvm-project/commit/026776fb60e52be04ea26d3d1d371d9efcb6ae3b.diff

LOG: [libc++] Refactor the creation of the global and classic locales (#72581)

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.

Added: 
    

Modified: 
    libcxx/include/__locale
    libcxx/src/locale.cpp
    libcxx/test/std/localization/locales/locale/locale.cons/char_pointer.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__locale b/libcxx/include/__locale
index b1502dd71edadf6..fcae49e23fac59e 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -127,6 +127,10 @@ private:
     class __imp;
     __imp* __locale_;
 
+    template <class> friend struct __no_destroy;
+    struct __private_tag { };
+    _LIBCPP_HIDE_FROM_ABI explicit locale(__private_tag, __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..f3b281d98825e44 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(__private_tag{}, &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

diff  --git a/libcxx/test/std/localization/locales/locale/locale.cons/char_pointer.pass.cpp b/libcxx/test/std/localization/locales/locale/locale.cons/char_pointer.pass.cpp
index 99131dd245fbdac..bd0693a542848b3 100644
--- a/libcxx/test/std/localization/locales/locale/locale.cons/char_pointer.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale/locale.cons/char_pointer.pass.cpp
@@ -81,21 +81,25 @@ int main(int, char**)
         assert(!(loc == loc3));
         assert(loc != loc3);
 #ifndef TEST_HAS_NO_EXCEPTIONS
-        try
-        {
+        try {
             std::locale((const char*)0);
             assert(false);
+        } catch (std::runtime_error&) {
+            // pass
         }
-        catch (std::runtime_error&)
-        {
+
+        try {
+            std::locale(nullptr);
+            assert(false);
+        } catch (std::runtime_error&) {
+            // pass
         }
-        try
-        {
+
+        try {
             std::locale("spazbot");
             assert(false);
-        }
-        catch (std::runtime_error&)
-        {
+        } catch (std::runtime_error&) {
+            // pass
         }
 #endif
         std::locale ok("");


        


More information about the libcxx-commits mailing list