1 //===------------------------ memory_resource.cpp -------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "experimental/memory_resource" 11 12 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 13 #include "atomic" 14 #elif !defined(_LIBCPP_HAS_NO_THREADS) 15 #include "mutex" 16 #endif 17 18 _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 19 20 // memory_resource 21 22 //memory_resource::~memory_resource() {} 23 24 // new_delete_resource() 25 26 class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp 27 : public memory_resource 28 { 29 public: 30 ~__new_delete_memory_resource_imp() = default; 31 32 protected: 33 virtual void* do_allocate(size_t __size, size_t __align) 34 { return _VSTD::__libcpp_allocate(__size, __align); /* FIXME */} 35 36 virtual void do_deallocate(void* __p, size_t __n, size_t __align) { 37 _VSTD::__libcpp_deallocate(__p, __n, __align); /* FIXME */ 38 } 39 40 virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 41 { return &__other == this; } 42 }; 43 44 // null_memory_resource() 45 46 class _LIBCPP_TYPE_VIS __null_memory_resource_imp 47 : public memory_resource 48 { 49 public: 50 ~__null_memory_resource_imp() = default; 51 52 protected: 53 virtual void* do_allocate(size_t, size_t) { 54 __throw_bad_alloc(); 55 } 56 virtual void do_deallocate(void *, size_t, size_t) {} 57 virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 58 { return &__other == this; } 59 }; 60 61 namespace { 62 63 union ResourceInitHelper { 64 struct { 65 __new_delete_memory_resource_imp new_delete_res; 66 __null_memory_resource_imp null_res; 67 } resources; 68 char dummy; 69 _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} 70 ~ResourceInitHelper() {} 71 }; 72 73 // Detect if the init_priority attribute is supported. 74 #if (defined(_LIBCPP_COMPILER_GCC) && defined(__APPLE__)) \ 75 || defined(_LIBCPP_COMPILER_MSVC) 76 // GCC on Apple doesn't support the init priority attribute, 77 // and MSVC doesn't support any GCC attributes. 78 # define _LIBCPP_INIT_PRIORITY_MAX 79 #else 80 # define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101))) 81 #endif 82 83 // When compiled in C++14 this initialization should be a constant expression. 84 // Only in C++11 is "init_priority" needed to ensure initialization order. 85 #if _LIBCPP_STD_VER > 11 86 _LIBCPP_SAFE_STATIC 87 #endif 88 ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; 89 90 } // end namespace 91 92 93 memory_resource * new_delete_resource() _NOEXCEPT { 94 return &res_init.resources.new_delete_res; 95 } 96 97 memory_resource * null_memory_resource() _NOEXCEPT { 98 return &res_init.resources.null_res; 99 } 100 101 // default_memory_resource() 102 103 static memory_resource * 104 __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT 105 { 106 #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 107 _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = 108 ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); 109 if (set) { 110 new_res = new_res ? new_res : new_delete_resource(); 111 // TODO: Can a weaker ordering be used? 112 return _VSTD::atomic_exchange_explicit( 113 &__res, new_res, memory_order::memory_order_acq_rel); 114 } 115 else { 116 return _VSTD::atomic_load_explicit( 117 &__res, memory_order::memory_order_acquire); 118 } 119 #elif !defined(_LIBCPP_HAS_NO_THREADS) 120 _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; 121 static mutex res_lock; 122 if (set) { 123 new_res = new_res ? new_res : new_delete_resource(); 124 lock_guard<mutex> guard(res_lock); 125 memory_resource * old_res = res; 126 res = new_res; 127 return old_res; 128 } else { 129 lock_guard<mutex> guard(res_lock); 130 return res; 131 } 132 #else 133 _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; 134 if (set) { 135 new_res = new_res ? new_res : new_delete_resource(); 136 memory_resource * old_res = res; 137 res = new_res; 138 return old_res; 139 } else { 140 return res; 141 } 142 #endif 143 } 144 145 memory_resource * get_default_resource() _NOEXCEPT 146 { 147 return __default_memory_resource(); 148 } 149 150 memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT 151 { 152 return __default_memory_resource(true, __new_res); 153 } 154 155 _LIBCPP_END_NAMESPACE_LFTS_PMR 156