1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <experimental/memory_resource> 10 11 _LIBCPP_SUPPRESS_DEPRECATED_PUSH 12 13 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 14 # include <atomic> 15 #elif !defined(_LIBCPP_HAS_NO_THREADS) 16 # include <mutex> 17 # if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 18 # pragma comment(lib, "pthread") 19 # endif 20 #endif 21 22 _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 23 24 // memory_resource 25 26 //memory_resource::~memory_resource() {} 27 28 // new_delete_resource() 29 30 class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp 31 : public memory_resource 32 { 33 void *do_allocate(size_t size, size_t align) override { 34 #ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION 35 if (__is_overaligned_for_new(align)) 36 __throw_bad_alloc(); 37 #endif 38 return _VSTD::__libcpp_allocate(size, align); 39 } 40 41 void do_deallocate(void *p, size_t n, size_t align) override { 42 _VSTD::__libcpp_deallocate(p, n, align); 43 } 44 45 bool do_is_equal(memory_resource const & other) const noexcept override 46 { return &other == this; } 47 48 public: 49 ~__new_delete_memory_resource_imp() override = default; 50 }; 51 52 // null_memory_resource() 53 54 class _LIBCPP_TYPE_VIS __null_memory_resource_imp 55 : public memory_resource 56 { 57 public: 58 ~__null_memory_resource_imp() = default; 59 60 protected: 61 virtual void* do_allocate(size_t, size_t) { 62 __throw_bad_alloc(); 63 } 64 virtual void do_deallocate(void *, size_t, size_t) {} 65 virtual bool do_is_equal(memory_resource const & __other) const noexcept 66 { return &__other == this; } 67 }; 68 69 namespace { 70 71 union ResourceInitHelper { 72 struct { 73 __new_delete_memory_resource_imp new_delete_res; 74 __null_memory_resource_imp null_res; 75 } resources; 76 char dummy; 77 _LIBCPP_CONSTEXPR_SINCE_CXX14 ResourceInitHelper() : resources() {} 78 ~ResourceInitHelper() {} 79 }; 80 81 // Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority 82 // attribute with a value that's reserved for the implementation (we're the implementation). 83 #include "memory_resource_init_helper.h" 84 85 } // end namespace 86 87 88 memory_resource * new_delete_resource() noexcept { 89 return &res_init.resources.new_delete_res; 90 } 91 92 memory_resource * null_memory_resource() noexcept { 93 return &res_init.resources.null_res; 94 } 95 96 // default_memory_resource() 97 98 static memory_resource * 99 __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept 100 { 101 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 102 static constinit atomic<memory_resource*> __res{&res_init.resources.new_delete_res}; 103 if (set) { 104 new_res = new_res ? new_res : new_delete_resource(); 105 // TODO: Can a weaker ordering be used? 106 return _VSTD::atomic_exchange_explicit( 107 &__res, new_res, memory_order_acq_rel); 108 } 109 else { 110 return _VSTD::atomic_load_explicit( 111 &__res, memory_order_acquire); 112 } 113 #elif !defined(_LIBCPP_HAS_NO_THREADS) 114 static constinit memory_resource *res = &res_init.resources.new_delete_res; 115 static mutex res_lock; 116 if (set) { 117 new_res = new_res ? new_res : new_delete_resource(); 118 lock_guard<mutex> guard(res_lock); 119 memory_resource * old_res = res; 120 res = new_res; 121 return old_res; 122 } else { 123 lock_guard<mutex> guard(res_lock); 124 return res; 125 } 126 #else 127 static constinit memory_resource *res = &res_init.resources.new_delete_res; 128 if (set) { 129 new_res = new_res ? new_res : new_delete_resource(); 130 memory_resource * old_res = res; 131 res = new_res; 132 return old_res; 133 } else { 134 return res; 135 } 136 #endif 137 } 138 139 memory_resource * get_default_resource() noexcept 140 { 141 return __default_memory_resource(); 142 } 143 144 memory_resource * set_default_resource(memory_resource * __new_res) noexcept 145 { 146 return __default_memory_resource(true, __new_res); 147 } 148 149 _LIBCPP_END_NAMESPACE_LFTS_PMR 150