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 // When compiled in C++14 this initialization should be a constant expression. 80 // Only in C++11 is "init_priority" needed to ensure initialization order. 81 #if _LIBCPP_STD_VER > 11 82 _LIBCPP_SAFE_STATIC 83 #endif 84 ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; 85 86 } // end namespace 87 88 89 memory_resource * new_delete_resource() _NOEXCEPT { 90 return &res_init.resources.new_delete_res; 91 } 92 93 memory_resource * null_memory_resource() _NOEXCEPT { 94 return &res_init.resources.null_res; 95 } 96 97 // default_memory_resource() 98 99 static memory_resource * 100 __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT 101 { 102 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 103 _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = 104 ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); 105 if (set) { 106 new_res = new_res ? new_res : new_delete_resource(); 107 // TODO: Can a weaker ordering be used? 108 return _VSTD::atomic_exchange_explicit( 109 &__res, new_res, memory_order_acq_rel); 110 } 111 else { 112 return _VSTD::atomic_load_explicit( 113 &__res, memory_order_acquire); 114 } 115 #elif !defined(_LIBCPP_HAS_NO_THREADS) 116 _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; 117 static mutex res_lock; 118 if (set) { 119 new_res = new_res ? new_res : new_delete_resource(); 120 lock_guard<mutex> guard(res_lock); 121 memory_resource * old_res = res; 122 res = new_res; 123 return old_res; 124 } else { 125 lock_guard<mutex> guard(res_lock); 126 return res; 127 } 128 #else 129 _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; 130 if (set) { 131 new_res = new_res ? new_res : new_delete_resource(); 132 memory_resource * old_res = res; 133 res = new_res; 134 return old_res; 135 } else { 136 return res; 137 } 138 #endif 139 } 140 141 memory_resource * get_default_resource() _NOEXCEPT 142 { 143 return __default_memory_resource(); 144 } 145 146 memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT 147 { 148 return __default_memory_resource(true, __new_res); 149 } 150 151 _LIBCPP_END_NAMESPACE_LFTS_PMR 152