1*4d6fc14bSjoerg //===------------------------ memory_resource.cpp -------------------------===//
2*4d6fc14bSjoerg //
3*4d6fc14bSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4d6fc14bSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*4d6fc14bSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4d6fc14bSjoerg //
7*4d6fc14bSjoerg //===----------------------------------------------------------------------===//
8*4d6fc14bSjoerg
9*4d6fc14bSjoerg #include "experimental/memory_resource"
10*4d6fc14bSjoerg
11*4d6fc14bSjoerg #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
12*4d6fc14bSjoerg #include "atomic"
13*4d6fc14bSjoerg #elif !defined(_LIBCPP_HAS_NO_THREADS)
14*4d6fc14bSjoerg #include "mutex"
15*4d6fc14bSjoerg #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
16*4d6fc14bSjoerg #pragma comment(lib, "pthread")
17*4d6fc14bSjoerg #endif
18*4d6fc14bSjoerg #endif
19*4d6fc14bSjoerg
20*4d6fc14bSjoerg _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
21*4d6fc14bSjoerg
22*4d6fc14bSjoerg // memory_resource
23*4d6fc14bSjoerg
24*4d6fc14bSjoerg //memory_resource::~memory_resource() {}
25*4d6fc14bSjoerg
26*4d6fc14bSjoerg // new_delete_resource()
27*4d6fc14bSjoerg
28*4d6fc14bSjoerg class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp
29*4d6fc14bSjoerg : public memory_resource
30*4d6fc14bSjoerg {
do_allocate(size_t size,size_t align)31*4d6fc14bSjoerg void *do_allocate(size_t size, size_t align) override {
32*4d6fc14bSjoerg #ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
33*4d6fc14bSjoerg if (__is_overaligned_for_new(align))
34*4d6fc14bSjoerg __throw_bad_alloc();
35*4d6fc14bSjoerg #endif
36*4d6fc14bSjoerg return _VSTD::__libcpp_allocate(size, align);
37*4d6fc14bSjoerg }
38*4d6fc14bSjoerg
do_deallocate(void * p,size_t n,size_t align)39*4d6fc14bSjoerg void do_deallocate(void *p, size_t n, size_t align) override {
40*4d6fc14bSjoerg _VSTD::__libcpp_deallocate(p, n, align);
41*4d6fc14bSjoerg }
42*4d6fc14bSjoerg
do_is_equal(memory_resource const & other) const43*4d6fc14bSjoerg bool do_is_equal(memory_resource const & other) const noexcept override
44*4d6fc14bSjoerg { return &other == this; }
45*4d6fc14bSjoerg
46*4d6fc14bSjoerg public:
47*4d6fc14bSjoerg ~__new_delete_memory_resource_imp() override = default;
48*4d6fc14bSjoerg };
49*4d6fc14bSjoerg
50*4d6fc14bSjoerg // null_memory_resource()
51*4d6fc14bSjoerg
52*4d6fc14bSjoerg class _LIBCPP_TYPE_VIS __null_memory_resource_imp
53*4d6fc14bSjoerg : public memory_resource
54*4d6fc14bSjoerg {
55*4d6fc14bSjoerg public:
56*4d6fc14bSjoerg ~__null_memory_resource_imp() = default;
57*4d6fc14bSjoerg
58*4d6fc14bSjoerg protected:
do_allocate(size_t,size_t)59*4d6fc14bSjoerg virtual void* do_allocate(size_t, size_t) {
60*4d6fc14bSjoerg __throw_bad_alloc();
61*4d6fc14bSjoerg }
do_deallocate(void *,size_t,size_t)62*4d6fc14bSjoerg virtual void do_deallocate(void *, size_t, size_t) {}
do_is_equal(memory_resource const & __other) const63*4d6fc14bSjoerg virtual bool do_is_equal(memory_resource const & __other) const noexcept
64*4d6fc14bSjoerg { return &__other == this; }
65*4d6fc14bSjoerg };
66*4d6fc14bSjoerg
67*4d6fc14bSjoerg namespace {
68*4d6fc14bSjoerg
69*4d6fc14bSjoerg union ResourceInitHelper {
70*4d6fc14bSjoerg struct {
71*4d6fc14bSjoerg __new_delete_memory_resource_imp new_delete_res;
72*4d6fc14bSjoerg __null_memory_resource_imp null_res;
73*4d6fc14bSjoerg } resources;
74*4d6fc14bSjoerg char dummy;
ResourceInitHelper()75*4d6fc14bSjoerg _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
~ResourceInitHelper()76*4d6fc14bSjoerg ~ResourceInitHelper() {}
77*4d6fc14bSjoerg };
78*4d6fc14bSjoerg
79*4d6fc14bSjoerg _LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX;
80*4d6fc14bSjoerg
81*4d6fc14bSjoerg } // end namespace
82*4d6fc14bSjoerg
83*4d6fc14bSjoerg
new_delete_resource()84*4d6fc14bSjoerg memory_resource * new_delete_resource() noexcept {
85*4d6fc14bSjoerg return &res_init.resources.new_delete_res;
86*4d6fc14bSjoerg }
87*4d6fc14bSjoerg
null_memory_resource()88*4d6fc14bSjoerg memory_resource * null_memory_resource() noexcept {
89*4d6fc14bSjoerg return &res_init.resources.null_res;
90*4d6fc14bSjoerg }
91*4d6fc14bSjoerg
92*4d6fc14bSjoerg // default_memory_resource()
93*4d6fc14bSjoerg
94*4d6fc14bSjoerg static memory_resource *
__default_memory_resource(bool set=false,memory_resource * new_res=nullptr)95*4d6fc14bSjoerg __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept
96*4d6fc14bSjoerg {
97*4d6fc14bSjoerg #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
98*4d6fc14bSjoerg _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res =
99*4d6fc14bSjoerg ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
100*4d6fc14bSjoerg if (set) {
101*4d6fc14bSjoerg new_res = new_res ? new_res : new_delete_resource();
102*4d6fc14bSjoerg // TODO: Can a weaker ordering be used?
103*4d6fc14bSjoerg return _VSTD::atomic_exchange_explicit(
104*4d6fc14bSjoerg &__res, new_res, memory_order_acq_rel);
105*4d6fc14bSjoerg }
106*4d6fc14bSjoerg else {
107*4d6fc14bSjoerg return _VSTD::atomic_load_explicit(
108*4d6fc14bSjoerg &__res, memory_order_acquire);
109*4d6fc14bSjoerg }
110*4d6fc14bSjoerg #elif !defined(_LIBCPP_HAS_NO_THREADS)
111*4d6fc14bSjoerg _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res;
112*4d6fc14bSjoerg static mutex res_lock;
113*4d6fc14bSjoerg if (set) {
114*4d6fc14bSjoerg new_res = new_res ? new_res : new_delete_resource();
115*4d6fc14bSjoerg lock_guard<mutex> guard(res_lock);
116*4d6fc14bSjoerg memory_resource * old_res = res;
117*4d6fc14bSjoerg res = new_res;
118*4d6fc14bSjoerg return old_res;
119*4d6fc14bSjoerg } else {
120*4d6fc14bSjoerg lock_guard<mutex> guard(res_lock);
121*4d6fc14bSjoerg return res;
122*4d6fc14bSjoerg }
123*4d6fc14bSjoerg #else
124*4d6fc14bSjoerg _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res;
125*4d6fc14bSjoerg if (set) {
126*4d6fc14bSjoerg new_res = new_res ? new_res : new_delete_resource();
127*4d6fc14bSjoerg memory_resource * old_res = res;
128*4d6fc14bSjoerg res = new_res;
129*4d6fc14bSjoerg return old_res;
130*4d6fc14bSjoerg } else {
131*4d6fc14bSjoerg return res;
132*4d6fc14bSjoerg }
133*4d6fc14bSjoerg #endif
134*4d6fc14bSjoerg }
135*4d6fc14bSjoerg
get_default_resource()136*4d6fc14bSjoerg memory_resource * get_default_resource() noexcept
137*4d6fc14bSjoerg {
138*4d6fc14bSjoerg return __default_memory_resource();
139*4d6fc14bSjoerg }
140*4d6fc14bSjoerg
set_default_resource(memory_resource * __new_res)141*4d6fc14bSjoerg memory_resource * set_default_resource(memory_resource * __new_res) noexcept
142*4d6fc14bSjoerg {
143*4d6fc14bSjoerg return __default_memory_resource(true, __new_res);
144*4d6fc14bSjoerg }
145*4d6fc14bSjoerg
146*4d6fc14bSjoerg _LIBCPP_END_NAMESPACE_LFTS_PMR
147