memory_resource.cpp revision 341825
1303237Sdim//===------------------------ memory_resource.cpp -------------------------===// 2303237Sdim// 3303237Sdim// The LLVM Compiler Infrastructure 4303237Sdim// 5303237Sdim// This file is dual licensed under the MIT and the University of Illinois Open 6303237Sdim// Source Licenses. See LICENSE.TXT for details. 7303237Sdim// 8303237Sdim//===----------------------------------------------------------------------===// 9303237Sdim 10303237Sdim#include "experimental/memory_resource" 11303237Sdim 12303237Sdim#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 13303237Sdim#include "atomic" 14303237Sdim#elif !defined(_LIBCPP_HAS_NO_THREADS) 15303237Sdim#include "mutex" 16303237Sdim#endif 17303237Sdim 18303237Sdim_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 19303237Sdim 20303237Sdim// memory_resource 21303237Sdim 22303237Sdim//memory_resource::~memory_resource() {} 23303237Sdim 24303237Sdim// new_delete_resource() 25303237Sdim 26314564Sdimclass _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp 27303237Sdim : public memory_resource 28303237Sdim{ 29303237Sdimpublic: 30303237Sdim ~__new_delete_memory_resource_imp() = default; 31303237Sdim 32303237Sdimprotected: 33303237Sdim virtual void* do_allocate(size_t __size, size_t __align) 34341825Sdim { return _VSTD::__libcpp_allocate(__size, __align); /* FIXME */} 35303237Sdim 36341825Sdim virtual void do_deallocate(void * __p, size_t, size_t __align) 37341825Sdim { _VSTD::__libcpp_deallocate(__p, __align); /* FIXME */ } 38303237Sdim 39303237Sdim virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 40303237Sdim { return &__other == this; } 41303237Sdim}; 42303237Sdim 43303237Sdim// null_memory_resource() 44303237Sdim 45314564Sdimclass _LIBCPP_TYPE_VIS __null_memory_resource_imp 46303237Sdim : public memory_resource 47303237Sdim{ 48303237Sdimpublic: 49303237Sdim ~__null_memory_resource_imp() = default; 50303237Sdim 51303237Sdimprotected: 52303237Sdim virtual void* do_allocate(size_t, size_t) { 53314564Sdim __throw_bad_alloc(); 54303237Sdim } 55303237Sdim virtual void do_deallocate(void *, size_t, size_t) {} 56303237Sdim virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 57303237Sdim { return &__other == this; } 58303237Sdim}; 59303237Sdim 60303237Sdimnamespace { 61303237Sdim 62303237Sdimunion ResourceInitHelper { 63303237Sdim struct { 64303237Sdim __new_delete_memory_resource_imp new_delete_res; 65303237Sdim __null_memory_resource_imp null_res; 66303237Sdim } resources; 67303237Sdim char dummy; 68303237Sdim _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} 69303237Sdim ~ResourceInitHelper() {} 70303237Sdim}; 71341825Sdim 72341825Sdim// Detect if the init_priority attribute is supported. 73341825Sdim#if (defined(_LIBCPP_COMPILER_GCC) && defined(__APPLE__)) \ 74341825Sdim || defined(_LIBCPP_COMPILER_MSVC) 75341825Sdim// GCC on Apple doesn't support the init priority attribute, 76341825Sdim// and MSVC doesn't support any GCC attributes. 77341825Sdim# define _LIBCPP_INIT_PRIORITY_MAX 78341825Sdim#else 79341825Sdim# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101))) 80341825Sdim#endif 81341825Sdim 82303237Sdim// When compiled in C++14 this initialization should be a constant expression. 83303237Sdim// Only in C++11 is "init_priority" needed to ensure initialization order. 84314564Sdim#if _LIBCPP_STD_VER > 11 85314564Sdim_LIBCPP_SAFE_STATIC 86314564Sdim#endif 87341825SdimResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; 88303237Sdim 89303237Sdim} // end namespace 90303237Sdim 91303237Sdim 92303237Sdimmemory_resource * new_delete_resource() _NOEXCEPT { 93303237Sdim return &res_init.resources.new_delete_res; 94303237Sdim} 95303237Sdim 96303237Sdimmemory_resource * null_memory_resource() _NOEXCEPT { 97303237Sdim return &res_init.resources.null_res; 98303237Sdim} 99303237Sdim 100303237Sdim// default_memory_resource() 101303237Sdim 102303237Sdimstatic memory_resource * 103303237Sdim__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT 104303237Sdim{ 105303237Sdim#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 106314564Sdim _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = 107303237Sdim ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); 108303237Sdim if (set) { 109303237Sdim new_res = new_res ? new_res : new_delete_resource(); 110303237Sdim // TODO: Can a weaker ordering be used? 111303237Sdim return _VSTD::atomic_exchange_explicit( 112303237Sdim &__res, new_res, memory_order::memory_order_acq_rel); 113303237Sdim } 114303237Sdim else { 115303237Sdim return _VSTD::atomic_load_explicit( 116303237Sdim &__res, memory_order::memory_order_acquire); 117303237Sdim } 118303237Sdim#elif !defined(_LIBCPP_HAS_NO_THREADS) 119314564Sdim _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; 120303237Sdim static mutex res_lock; 121303237Sdim if (set) { 122303237Sdim new_res = new_res ? new_res : new_delete_resource(); 123303237Sdim lock_guard<mutex> guard(res_lock); 124303237Sdim memory_resource * old_res = res; 125303237Sdim res = new_res; 126303237Sdim return old_res; 127303237Sdim } else { 128303237Sdim lock_guard<mutex> guard(res_lock); 129303237Sdim return res; 130303237Sdim } 131303237Sdim#else 132314564Sdim _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; 133303237Sdim if (set) { 134303237Sdim new_res = new_res ? new_res : new_delete_resource(); 135303237Sdim memory_resource * old_res = res; 136303237Sdim res = new_res; 137303237Sdim return old_res; 138303237Sdim } else { 139303237Sdim return res; 140303237Sdim } 141303237Sdim#endif 142303237Sdim} 143303237Sdim 144303237Sdimmemory_resource * get_default_resource() _NOEXCEPT 145303237Sdim{ 146303237Sdim return __default_memory_resource(); 147303237Sdim} 148303237Sdim 149303237Sdimmemory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT 150303237Sdim{ 151303237Sdim return __default_memory_resource(true, __new_res); 152303237Sdim} 153303237Sdim 154314564Sdim_LIBCPP_END_NAMESPACE_LFTS_PMR 155