xref: /netbsd-src/external/apache2/llvm/dist/libcxx/src/experimental/memory_resource.cpp (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
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