[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