memory_resource.cpp revision 303237
198937Sdes//===------------------------ memory_resource.cpp -------------------------===// 298937Sdes// 398937Sdes// The LLVM Compiler Infrastructure 498937Sdes// 598937Sdes// This file is dual licensed under the MIT and the University of Illinois Open 6147001Sdes// Source Licenses. See LICENSE.TXT for details. 7126274Sdes// 898937Sdes//===----------------------------------------------------------------------===// 998937Sdes 1098937Sdes#include "experimental/memory_resource" 1198937Sdes 12126274Sdes#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 13106121Sdes#include "atomic" 1498937Sdes#elif !defined(_LIBCPP_HAS_NO_THREADS) 15162852Sdes#include "mutex" 16162852Sdes#endif 17126274Sdes 18126274Sdes_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 19181111Sdes 20181111Sdes// memory_resource 21181111Sdes 2298937Sdes//memory_resource::~memory_resource() {} 23181111Sdes 24181111Sdes// new_delete_resource() 25181111Sdes 26181111Sdesclass _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp 27181111Sdes : public memory_resource 28181111Sdes{ 29181111Sdespublic: 30181111Sdes ~__new_delete_memory_resource_imp() = default; 31181111Sdes 32181111Sdesprotected: 33181111Sdes virtual void* do_allocate(size_t __size, size_t __align) 34181111Sdes { return __allocate(__size); } 35181111Sdes 36181111Sdes virtual void do_deallocate(void * __p, size_t, size_t) 3798937Sdes { __deallocate(__p); } 3898937Sdes 39181111Sdes virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 40181111Sdes { return &__other == this; } 41181111Sdes}; 42181111Sdes 43181111Sdes// null_memory_resource() 44181111Sdes 45181111Sdesclass _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp 46181111Sdes : public memory_resource 47181111Sdes{ 48181111Sdespublic: 4998937Sdes ~__null_memory_resource_imp() = default; 5098937Sdes 5198937Sdesprotected: 5298937Sdes virtual void* do_allocate(size_t, size_t) { 5398937Sdes#ifndef _LIBCPP_NO_EXCEPTIONS 5498937Sdes throw std::bad_alloc(); 55137015Sdes#else 5698937Sdes abort(); 5798937Sdes#endif 58124208Sdes } 5998937Sdes virtual void do_deallocate(void *, size_t, size_t) {} 60181111Sdes virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 6198937Sdes { return &__other == this; } 62181111Sdes}; 63181111Sdes 64181111Sdesnamespace { 65181111Sdes 6698937Sdesunion ResourceInitHelper { 67181111Sdes struct { 6898937Sdes __new_delete_memory_resource_imp new_delete_res; 6998937Sdes __null_memory_resource_imp null_res; 70147001Sdes } resources; 71147001Sdes char dummy; 72147001Sdes _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} 73147001Sdes ~ResourceInitHelper() {} 7498937Sdes}; 7598937Sdes// When compiled in C++14 this initialization should be a constant expression. 76146998Sdes// Only in C++11 is "init_priority" needed to ensure initialization order. 77147001SdesResourceInitHelper res_init __attribute__((init_priority (101))); 78162852Sdes 79162852Sdes} // end namespace 80162852Sdes 81162852Sdes 82146998Sdesmemory_resource * new_delete_resource() _NOEXCEPT { 83146998Sdes return &res_init.resources.new_delete_res; 84146998Sdes} 85162852Sdes 86162852Sdesmemory_resource * null_memory_resource() _NOEXCEPT { 87162852Sdes return &res_init.resources.null_res; 88181111Sdes} 89181111Sdes 90181111Sdes// default_memory_resource() 91162852Sdes 92162852Sdesstatic memory_resource * 93162852Sdes__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT 94162852Sdes{ 95162852Sdes#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 96162852Sdes static atomic<memory_resource*> __res = 97162852Sdes ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); 98162852Sdes if (set) { 99162852Sdes new_res = new_res ? new_res : new_delete_resource(); 100162852Sdes // TODO: Can a weaker ordering be used? 10198937Sdes return _VSTD::atomic_exchange_explicit( 10298937Sdes &__res, new_res, memory_order::memory_order_acq_rel); 10398937Sdes } 10498937Sdes else { 10598937Sdes return _VSTD::atomic_load_explicit( 10698937Sdes &__res, memory_order::memory_order_acquire); 10798937Sdes } 10898937Sdes#elif !defined(_LIBCPP_HAS_NO_THREADS) 10998937Sdes static memory_resource * res = &res_init.resources.new_delete_res; 11098937Sdes static mutex res_lock; 11198937Sdes if (set) { 11298937Sdes new_res = new_res ? new_res : new_delete_resource(); 11398937Sdes lock_guard<mutex> guard(res_lock); 11498937Sdes memory_resource * old_res = res; 11598937Sdes res = new_res; 11698937Sdes return old_res; 11798937Sdes } else { 118126274Sdes lock_guard<mutex> guard(res_lock); 11998937Sdes return res; 12098937Sdes } 12198937Sdes#else 12298937Sdes static memory_resource* res = &res_init.resources.new_delete_res; 12398937Sdes if (set) { 12498937Sdes new_res = new_res ? new_res : new_delete_resource(); 12598937Sdes memory_resource * old_res = res; 12698937Sdes res = new_res; 12798937Sdes return old_res; 128147001Sdes } else { 129147001Sdes return res; 130147001Sdes } 131147001Sdes#endif 13298937Sdes} 13398937Sdes 13498937Sdesmemory_resource * get_default_resource() _NOEXCEPT 13598937Sdes{ 13698937Sdes return __default_memory_resource(); 13798937Sdes} 13898937Sdes 13998937Sdesmemory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT 14098937Sdes{ 14198937Sdes return __default_memory_resource(true, __new_res); 14298937Sdes} 14398937Sdes 14498937Sdes_LIBCPP_END_NAMESPACE_LFTS_PMR