diff --git a/libcxx/include/__fwd/memory_resource.h b/libcxx/include/__fwd/memory_resource.h --- a/libcxx/include/__fwd/memory_resource.h +++ b/libcxx/include/__fwd/memory_resource.h @@ -15,13 +15,13 @@ # pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { template class _LIBCPP_TEMPLATE_VIS polymorphic_allocator; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP___FWD_MEMORY_RESOURCE_H diff --git a/libcxx/include/__fwd/string.h b/libcxx/include/__fwd/string.h --- a/libcxx/include/__fwd/string.h +++ b/libcxx/include/__fwd/string.h @@ -59,7 +59,11 @@ #if _LIBCPP_STD_VER >= 17 +_LIBCPP_END_NAMESPACE_STD + +namespace std { namespace pmr { + template > using basic_string = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; @@ -77,6 +81,9 @@ using u32string = basic_string; } // namespace pmr +} // namespace std + +_LIBCPP_BEGIN_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/__memory_resource/memory_resource.h b/libcxx/include/__memory_resource/memory_resource.h --- a/libcxx/include/__memory_resource/memory_resource.h +++ b/libcxx/include/__memory_resource/memory_resource.h @@ -18,7 +18,7 @@ #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { @@ -68,7 +68,7 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/__memory_resource/monotonic_buffer_resource.h b/libcxx/include/__memory_resource/monotonic_buffer_resource.h --- a/libcxx/include/__memory_resource/monotonic_buffer_resource.h +++ b/libcxx/include/__memory_resource/monotonic_buffer_resource.h @@ -20,7 +20,7 @@ #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { @@ -113,7 +113,7 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -28,7 +28,7 @@ #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { @@ -215,7 +215,7 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/__memory_resource/pool_options.h b/libcxx/include/__memory_resource/pool_options.h --- a/libcxx/include/__memory_resource/pool_options.h +++ b/libcxx/include/__memory_resource/pool_options.h @@ -18,7 +18,7 @@ #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { @@ -31,7 +31,7 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/__memory_resource/synchronized_pool_resource.h b/libcxx/include/__memory_resource/synchronized_pool_resource.h --- a/libcxx/include/__memory_resource/synchronized_pool_resource.h +++ b/libcxx/include/__memory_resource/synchronized_pool_resource.h @@ -24,7 +24,7 @@ #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { @@ -87,7 +87,7 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/__memory_resource/unsynchronized_pool_resource.h b/libcxx/include/__memory_resource/unsynchronized_pool_resource.h --- a/libcxx/include/__memory_resource/unsynchronized_pool_resource.h +++ b/libcxx/include/__memory_resource/unsynchronized_pool_resource.h @@ -21,7 +21,7 @@ #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { // purposefully not using versioning namespace namespace pmr { @@ -99,7 +99,7 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -2420,12 +2420,15 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { + namespace pmr { template using deque = std::deque<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif _LIBCPP_POP_MACROS diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -1780,12 +1780,16 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template using forward_list = std::forward_list<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif _LIBCPP_POP_MACROS diff --git a/libcxx/include/list b/libcxx/include/list --- a/libcxx/include/list +++ b/libcxx/include/list @@ -2363,12 +2363,16 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template using list = std::list<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif _LIBCPP_POP_MACROS diff --git a/libcxx/include/map b/libcxx/include/map --- a/libcxx/include/map +++ b/libcxx/include/map @@ -2340,7 +2340,9 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template > using map = std::map<_KeyT, _ValueT, _CompareT, polymorphic_allocator>>; @@ -2348,7 +2350,9 @@ template > using multimap = std::multimap<_KeyT, _ValueT, _CompareT, polymorphic_allocator>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 diff --git a/libcxx/include/regex b/libcxx/include/regex --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -6845,7 +6845,9 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template using match_results = std::match_results<_BidirT, polymorphic_allocator>>; @@ -6858,7 +6860,9 @@ using wsmatch = match_results; #endif } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif _LIBCPP_POP_MACROS diff --git a/libcxx/include/set b/libcxx/include/set --- a/libcxx/include/set +++ b/libcxx/include/set @@ -1585,7 +1585,9 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template > using set = std::set<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>; @@ -1593,7 +1595,9 @@ template > using multiset = std::multiset<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map --- a/libcxx/include/unordered_map +++ b/libcxx/include/unordered_map @@ -2630,7 +2630,9 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template , class _PredT = std::equal_to<_KeyT>> using unordered_map = @@ -2640,7 +2642,9 @@ using unordered_multimap = std::unordered_multimap<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set --- a/libcxx/include/unordered_set +++ b/libcxx/include/unordered_set @@ -1804,7 +1804,9 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD + +namespace std { + namespace pmr { template , class _PredT = std::equal_to<_KeyT>> using unordered_set = std::unordered_set<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>; @@ -1812,7 +1814,9 @@ template , class _PredT = std::equal_to<_KeyT>> using unordered_multiset = std::unordered_multiset<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -3345,12 +3345,15 @@ _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { + namespace pmr { template using vector = std::vector<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr -_LIBCPP_END_NAMESPACE_STD + +} // namespace std + #endif _LIBCPP_POP_MACROS diff --git a/libcxx/src/memory_resource.cpp b/libcxx/src/memory_resource.cpp --- a/libcxx/src/memory_resource.cpp +++ b/libcxx/src/memory_resource.cpp @@ -9,6 +9,12 @@ #include #include +#if defined(_LIBCPP_ABI_MICROSOFT) +# include "support/runtime/memory_resource_msvc.ipp" +#else +# include "support/runtime/memory_resource_fallback.ipp" +#endif + #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER # include #elif !defined(_LIBCPP_HAS_NO_THREADS) @@ -18,7 +24,7 @@ # endif #endif -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { namespace pmr { @@ -26,112 +32,6 @@ memory_resource::~memory_resource() = default; -// new_delete_resource() - -#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION -static bool is_aligned_to(void* ptr, size_t align) { - void* p2 = ptr; - size_t space = 1; - void* result = std::align(align, 1, p2, space); - return (result == ptr); -} -#endif - -class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp : public memory_resource { - void* do_allocate(size_t bytes, size_t align) override { -#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION - return std::__libcpp_allocate(bytes, align); -#else - if (bytes == 0) - bytes = 1; - void* result = std::__libcpp_allocate(bytes, align); - if (!is_aligned_to(result, align)) { - std::__libcpp_deallocate(result, bytes, align); - __throw_bad_alloc(); - } - return result; -#endif - } - - void do_deallocate(void* p, size_t bytes, size_t align) override { std::__libcpp_deallocate(p, bytes, align); } - - bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; } -}; - -// null_memory_resource() - -class _LIBCPP_TYPE_VIS __null_memory_resource_imp : public memory_resource { - void* do_allocate(size_t, size_t) override { __throw_bad_alloc(); } - void do_deallocate(void*, size_t, size_t) override {} - bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; } -}; - -namespace { - -union ResourceInitHelper { - struct { - __new_delete_memory_resource_imp new_delete_res; - __null_memory_resource_imp null_res; - } resources; - char dummy; - _LIBCPP_CONSTEXPR_SINCE_CXX14 ResourceInitHelper() : resources() {} - ~ResourceInitHelper() {} -}; - -// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority -// attribute with a value that's reserved for the implementation (we're the implementation). -#include "memory_resource_init_helper.h" - -} // end namespace - -memory_resource* new_delete_resource() noexcept { return &res_init.resources.new_delete_res; } - -memory_resource* null_memory_resource() noexcept { return &res_init.resources.null_res; } - -// default_memory_resource() - -static memory_resource* __default_memory_resource(bool set = false, memory_resource* new_res = nullptr) noexcept { -#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER - static constinit atomic __res{&res_init.resources.new_delete_res}; - if (set) { - new_res = new_res ? new_res : new_delete_resource(); - // TODO: Can a weaker ordering be used? - return std::atomic_exchange_explicit(&__res, new_res, memory_order_acq_rel); - } else { - return std::atomic_load_explicit(&__res, memory_order_acquire); - } -#elif !defined(_LIBCPP_HAS_NO_THREADS) - static constinit memory_resource* res = &res_init.resources.new_delete_res; - static mutex res_lock; - if (set) { - new_res = new_res ? new_res : new_delete_resource(); - lock_guard guard(res_lock); - memory_resource* old_res = res; - res = new_res; - return old_res; - } else { - lock_guard guard(res_lock); - return res; - } -#else - static constinit memory_resource* res = &res_init.resources.new_delete_res; - if (set) { - new_res = new_res ? new_res : new_delete_resource(); - memory_resource* old_res = res; - res = new_res; - return old_res; - } else { - return res; - } -#endif -} - -memory_resource* get_default_resource() noexcept { return __default_memory_resource(); } - -memory_resource* set_default_resource(memory_resource* __new_res) noexcept { - return __default_memory_resource(true, __new_res); -} - // 23.12.5, mem.res.pool static size_t roundup(size_t count, size_t alignment) { @@ -493,4 +393,4 @@ } // namespace pmr -_LIBCPP_END_NAMESPACE_STD +} // namespace std diff --git a/libcxx/src/support/runtime/memory_resource_fallback.ipp b/libcxx/src/support/runtime/memory_resource_fallback.ipp new file mode 100644 --- /dev/null +++ b/libcxx/src/support/runtime/memory_resource_fallback.ipp @@ -0,0 +1,121 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +namespace std { + +namespace pmr { + +// new_delete_resource() + +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION +static bool is_aligned_to(void* ptr, size_t align) { + void* p2 = ptr; + size_t space = 1; + void* result = std::align(align, 1, p2, space); + return (result == ptr); +} +#endif + +class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp : public memory_resource { + void* do_allocate(size_t bytes, size_t align) override { +#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + return std::__libcpp_allocate(bytes, align); +#else + if (bytes == 0) + bytes = 1; + void* result = std::__libcpp_allocate(bytes, align); + if (!is_aligned_to(result, align)) { + std::__libcpp_deallocate(result, bytes, align); + __throw_bad_alloc(); + } + return result; +#endif + } + + void do_deallocate(void* p, size_t bytes, size_t align) override { std::__libcpp_deallocate(p, bytes, align); } + + bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; } +}; + +// null_memory_resource() + +class _LIBCPP_TYPE_VIS __null_memory_resource_imp : public memory_resource { + void* do_allocate(size_t, size_t) override { __throw_bad_alloc(); } + void do_deallocate(void*, size_t, size_t) override {} + bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; } +}; + +namespace { + +union ResourceInitHelper { + struct { + __new_delete_memory_resource_imp new_delete_res; + __null_memory_resource_imp null_res; + } resources; + char dummy; + _LIBCPP_CONSTEXPR_SINCE_CXX14 ResourceInitHelper() : resources() {} + ~ResourceInitHelper() {} +}; + +// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority +// attribute with a value that's reserved for the implementation (we're the implementation). +#include "memory_resource_init_helper.h" + +} // end namespace + +memory_resource* new_delete_resource() noexcept { return &res_init.resources.new_delete_res; } + +memory_resource* null_memory_resource() noexcept { return &res_init.resources.null_res; } + +// default_memory_resource() + +static memory_resource* __default_memory_resource(bool set = false, memory_resource* new_res = nullptr) noexcept { +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER + static constinit atomic __res{&res_init.resources.new_delete_res}; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + // TODO: Can a weaker ordering be used? + return std::atomic_exchange_explicit(&__res, new_res, memory_order_acq_rel); + } else { + return std::atomic_load_explicit(&__res, memory_order_acquire); + } +#elif !defined(_LIBCPP_HAS_NO_THREADS) + static constinit memory_resource* res = &res_init.resources.new_delete_res; + static mutex res_lock; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + lock_guard guard(res_lock); + memory_resource* old_res = res; + res = new_res; + return old_res; + } else { + lock_guard guard(res_lock); + return res; + } +#else + static constinit memory_resource* res = &res_init.resources.new_delete_res; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + memory_resource* old_res = res; + res = new_res; + return old_res; + } else { + return res; + } +#endif +} + +memory_resource* get_default_resource() noexcept { return __default_memory_resource(); } + +memory_resource* set_default_resource(memory_resource* __new_res) noexcept { + return __default_memory_resource(true, __new_res); +} + +} // namespace pmr +} // namespace std diff --git a/libcxx/src/memory_resource_init_helper.h b/libcxx/src/support/runtime/memory_resource_init_helper.h rename from libcxx/src/memory_resource_init_helper.h rename to libcxx/src/support/runtime/memory_resource_init_helper.h diff --git a/libcxx/src/support/runtime/memory_resource_msvc.ipp b/libcxx/src/support/runtime/memory_resource_msvc.ipp new file mode 100644 --- /dev/null +++ b/libcxx/src/support/runtime/memory_resource_msvc.ipp @@ -0,0 +1,62 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_ABI_MICROSOFT +#error this header can only be used when targeting the MSVC ABI +#endif + +// default_memory_resource() + +extern "C" { + +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl _Aligned_set_default_resource(std::pmr::memory_resource*) noexcept; +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl _Unaligned_set_default_resource(std::pmr::memory_resource*) noexcept; +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl _Aligned_get_default_resource() noexcept; +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl _Unaligned_get_default_resource() noexcept; +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl _Aligned_new_delete_resource() noexcept; +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl _Unaligned_new_delete_resource() noexcept; +_LIBCPP_CRT_FUNC std::pmr::memory_resource* __cdecl null_memory_resource() noexcept; + +}; + +namespace std { + +namespace pmr { + +memory_resource* get_default_resource() noexcept { +#ifdef __cpp_aligned_new + return ::_Aligned_get_default_resource(); +#else + return ::_Unaligned_get_default_resource(); +#endif +} + +memory_resource* set_default_resource(memory_resource* __new_res) noexcept { +#ifdef __cpp_aligned_new + return ::_Aligned_set_default_resource(__new_res); +#else + return ::_Unaligned_set_default_resource(__new_res); +#endif +} + +memory_resource* new_delete_resource() noexcept { +#ifdef __cpp_aligned_new + return ::_Aligned_new_delete_resource(); +#else + return ::_Unaligned_new_delete_resource(); +#endif +} + +memory_resource* null_memory_resource() noexcept { + return ::null_memory_resource(); +} + +} // namespace pmr + +} // namespace std