1303237Sdim//===------------------------ memory_resource.cpp -------------------------===// 2303237Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303237Sdim// 7303237Sdim//===----------------------------------------------------------------------===// 8303237Sdim 9303237Sdim#include "experimental/memory_resource" 10303237Sdim 11303237Sdim#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 12303237Sdim#include "atomic" 13303237Sdim#elif !defined(_LIBCPP_HAS_NO_THREADS) 14303237Sdim#include "mutex" 15360784Sdim#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 16353358Sdim#pragma comment(lib, "pthread") 17303237Sdim#endif 18353358Sdim#endif 19303237Sdim 20303237Sdim_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 21303237Sdim 22303237Sdim// memory_resource 23303237Sdim 24303237Sdim//memory_resource::~memory_resource() {} 25303237Sdim 26303237Sdim// new_delete_resource() 27303237Sdim 28314564Sdimclass _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp 29303237Sdim : public memory_resource 30303237Sdim{ 31353358Sdim void *do_allocate(size_t size, size_t align) override { 32353358Sdim#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION 33353358Sdim if (__is_overaligned_for_new(align)) 34353358Sdim __throw_bad_alloc(); 35353358Sdim#endif 36353358Sdim return _VSTD::__libcpp_allocate(size, align); 37353358Sdim } 38303237Sdim 39353358Sdim void do_deallocate(void *p, size_t n, size_t align) override { 40353358Sdim _VSTD::__libcpp_deallocate(p, n, align); 41344779Sdim } 42303237Sdim 43353358Sdim bool do_is_equal(memory_resource const & other) const _NOEXCEPT override 44353358Sdim { return &other == this; } 45353358Sdim 46353358Sdimpublic: 47353358Sdim ~__new_delete_memory_resource_imp() override = default; 48303237Sdim}; 49303237Sdim 50303237Sdim// null_memory_resource() 51303237Sdim 52314564Sdimclass _LIBCPP_TYPE_VIS __null_memory_resource_imp 53303237Sdim : public memory_resource 54303237Sdim{ 55303237Sdimpublic: 56303237Sdim ~__null_memory_resource_imp() = default; 57303237Sdim 58303237Sdimprotected: 59303237Sdim virtual void* do_allocate(size_t, size_t) { 60314564Sdim __throw_bad_alloc(); 61303237Sdim } 62303237Sdim virtual void do_deallocate(void *, size_t, size_t) {} 63303237Sdim virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT 64303237Sdim { return &__other == this; } 65303237Sdim}; 66303237Sdim 67303237Sdimnamespace { 68303237Sdim 69303237Sdimunion ResourceInitHelper { 70303237Sdim struct { 71303237Sdim __new_delete_memory_resource_imp new_delete_res; 72303237Sdim __null_memory_resource_imp null_res; 73303237Sdim } resources; 74303237Sdim char dummy; 75303237Sdim _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} 76303237Sdim ~ResourceInitHelper() {} 77303237Sdim}; 78341825Sdim 79341825Sdim// Detect if the init_priority attribute is supported. 80341825Sdim#if (defined(_LIBCPP_COMPILER_GCC) && defined(__APPLE__)) \ 81341825Sdim || defined(_LIBCPP_COMPILER_MSVC) 82341825Sdim// GCC on Apple doesn't support the init priority attribute, 83341825Sdim// and MSVC doesn't support any GCC attributes. 84341825Sdim# define _LIBCPP_INIT_PRIORITY_MAX 85341825Sdim#else 86341825Sdim# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101))) 87341825Sdim#endif 88341825Sdim 89303237Sdim// When compiled in C++14 this initialization should be a constant expression. 90303237Sdim// Only in C++11 is "init_priority" needed to ensure initialization order. 91314564Sdim#if _LIBCPP_STD_VER > 11 92314564Sdim_LIBCPP_SAFE_STATIC 93314564Sdim#endif 94341825SdimResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; 95303237Sdim 96303237Sdim} // end namespace 97303237Sdim 98303237Sdim 99303237Sdimmemory_resource * new_delete_resource() _NOEXCEPT { 100303237Sdim return &res_init.resources.new_delete_res; 101303237Sdim} 102303237Sdim 103303237Sdimmemory_resource * null_memory_resource() _NOEXCEPT { 104303237Sdim return &res_init.resources.null_res; 105303237Sdim} 106303237Sdim 107303237Sdim// default_memory_resource() 108303237Sdim 109303237Sdimstatic memory_resource * 110303237Sdim__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT 111303237Sdim{ 112303237Sdim#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER 113314564Sdim _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = 114303237Sdim ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); 115303237Sdim if (set) { 116303237Sdim new_res = new_res ? new_res : new_delete_resource(); 117303237Sdim // TODO: Can a weaker ordering be used? 118303237Sdim return _VSTD::atomic_exchange_explicit( 119360784Sdim &__res, new_res, memory_order_acq_rel); 120303237Sdim } 121303237Sdim else { 122303237Sdim return _VSTD::atomic_load_explicit( 123360784Sdim &__res, memory_order_acquire); 124303237Sdim } 125303237Sdim#elif !defined(_LIBCPP_HAS_NO_THREADS) 126314564Sdim _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; 127303237Sdim static mutex res_lock; 128303237Sdim if (set) { 129303237Sdim new_res = new_res ? new_res : new_delete_resource(); 130303237Sdim lock_guard<mutex> guard(res_lock); 131303237Sdim memory_resource * old_res = res; 132303237Sdim res = new_res; 133303237Sdim return old_res; 134303237Sdim } else { 135303237Sdim lock_guard<mutex> guard(res_lock); 136303237Sdim return res; 137303237Sdim } 138303237Sdim#else 139314564Sdim _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; 140303237Sdim if (set) { 141303237Sdim new_res = new_res ? new_res : new_delete_resource(); 142303237Sdim memory_resource * old_res = res; 143303237Sdim res = new_res; 144303237Sdim return old_res; 145303237Sdim } else { 146303237Sdim return res; 147303237Sdim } 148303237Sdim#endif 149303237Sdim} 150303237Sdim 151303237Sdimmemory_resource * get_default_resource() _NOEXCEPT 152303237Sdim{ 153303237Sdim return __default_memory_resource(); 154303237Sdim} 155303237Sdim 156303237Sdimmemory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT 157303237Sdim{ 158303237Sdim return __default_memory_resource(true, __new_res); 159303237Sdim} 160303237Sdim 161314564Sdim_LIBCPP_END_NAMESPACE_LFTS_PMR 162