1 //===------------------------ memory_resource.cpp -------------------------===// 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 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 12 #include "atomic" 13 #elif !defined(_LIBCPP_HAS_NO_THREADS) 14 #include "mutex" 15 #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 16 #pragma comment(lib, "pthread") 17 #endif 18 #endif 19 20 _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 21 22 // memory_resource 23 24 //memory_resource::~memory_resource() {} 25 26 // new_delete_resource() 27 28 class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp 29 : public memory_resource 30 { 31 void *do_allocate(size_t size, size_t align) override { 32 #ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION 33 if (__is_overaligned_for_new(align)) 34 __throw_bad_alloc(); 35 #endif 36 return _VSTD::__libcpp_allocate(size, align); 37 } 38 39 void do_deallocate(void *p, size_t n, size_t align) override { 40 _VSTD::__libcpp_deallocate(p, n, align); 41 } 42 43 bool do_is_equal(memory_resource const & other) const noexcept override 44 { return &other == this; } 45 46 public: 47 ~__new_delete_memory_resource_imp() override = default; 48 }; 49 50 // null_memory_resource() 51 52 class _LIBCPP_TYPE_VIS __null_memory_resource_imp 53 : public memory_resource 54 { 55 public: 56 ~__null_memory_resource_imp() = default; 57 58 protected: 59 virtual void* do_allocate(size_t, size_t) { 60 __throw_bad_alloc(); 61 } 62 virtual void do_deallocate(void *, size_t, size_t) {} 63 virtual bool do_is_equal(memory_resource const & __other) const noexcept 64 { return &__other == this; } 65 }; 66 67 namespace { 68 69 union ResourceInitHelper { 70 struct { 71 __new_delete_memory_resource_imp new_delete_res; 72 __null_memory_resource_imp null_res; 73 } resources; 74 char dummy; 75 _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} 76 ~ResourceInitHelper() {} 77 }; 78 79 _LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; 80 81 } // end namespace 82 83 84 memory_resource * new_delete_resource() noexcept { 85 return &res_init.resources.new_delete_res; 86 } 87 88 memory_resource * null_memory_resource() noexcept { 89 return &res_init.resources.null_res; 90 } 91 92 // default_memory_resource() 93 94 static memory_resource * 95 __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept 96 { 97 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 98 _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = 99 ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); 100 if (set) { 101 new_res = new_res ? new_res : new_delete_resource(); 102 // TODO: Can a weaker ordering be used? 103 return _VSTD::atomic_exchange_explicit( 104 &__res, new_res, memory_order_acq_rel); 105 } 106 else { 107 return _VSTD::atomic_load_explicit( 108 &__res, memory_order_acquire); 109 } 110 #elif !defined(_LIBCPP_HAS_NO_THREADS) 111 _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; 112 static mutex res_lock; 113 if (set) { 114 new_res = new_res ? new_res : new_delete_resource(); 115 lock_guard<mutex> guard(res_lock); 116 memory_resource * old_res = res; 117 res = new_res; 118 return old_res; 119 } else { 120 lock_guard<mutex> guard(res_lock); 121 return res; 122 } 123 #else 124 _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; 125 if (set) { 126 new_res = new_res ? new_res : new_delete_resource(); 127 memory_resource * old_res = res; 128 res = new_res; 129 return old_res; 130 } else { 131 return res; 132 } 133 #endif 134 } 135 136 memory_resource * get_default_resource() noexcept 137 { 138 return __default_memory_resource(); 139 } 140 141 memory_resource * set_default_resource(memory_resource * __new_res) noexcept 142 { 143 return __default_memory_resource(true, __new_res); 144 } 145 146 _LIBCPP_END_NAMESPACE_LFTS_PMR 147