1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
215551efdSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
615551efdSEric Fiselier //
715551efdSEric Fiselier //===----------------------------------------------------------------------===//
815551efdSEric Fiselier 
9*bbb0f2c7SArthur O'Dwyer #include <experimental/memory_resource>
1015551efdSEric Fiselier 
1115551efdSEric Fiselier #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
12*bbb0f2c7SArthur O'Dwyer #  include <atomic>
132266a8d4SEric Fiselier #elif !defined(_LIBCPP_HAS_NO_THREADS)
14*bbb0f2c7SArthur O'Dwyer #  include <mutex>
15a9b5fff5SMichał Górny #  if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
16996e62eeSPetr Hosek #    pragma comment(lib, "pthread")
17996e62eeSPetr Hosek #  endif
1815551efdSEric Fiselier #endif
1915551efdSEric Fiselier 
2015551efdSEric Fiselier _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
2115551efdSEric Fiselier 
2215551efdSEric Fiselier // memory_resource
2315551efdSEric Fiselier 
2415551efdSEric Fiselier //memory_resource::~memory_resource() {}
2515551efdSEric Fiselier 
2615551efdSEric Fiselier // new_delete_resource()
2715551efdSEric Fiselier 
28e2f2d1edSEric Fiselier class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp
2915551efdSEric Fiselier     : public memory_resource
3015551efdSEric Fiselier {
do_allocate(size_t size,size_t align)317ffcd984SEric Fiselier     void *do_allocate(size_t size, size_t align) override {
327ffcd984SEric Fiselier #ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
337ffcd984SEric Fiselier         if (__is_overaligned_for_new(align))
347ffcd984SEric Fiselier             __throw_bad_alloc();
357ffcd984SEric Fiselier #endif
367ffcd984SEric Fiselier         return _VSTD::__libcpp_allocate(size, align);
37f25b75b9SEric Fiselier     }
3815551efdSEric Fiselier 
do_deallocate(void * p,size_t n,size_t align)397ffcd984SEric Fiselier     void do_deallocate(void *p, size_t n, size_t align) override {
407ffcd984SEric Fiselier       _VSTD::__libcpp_deallocate(p, n, align);
417ffcd984SEric Fiselier     }
427ffcd984SEric Fiselier 
do_is_equal(memory_resource const & other) const435601305fSLouis Dionne     bool do_is_equal(memory_resource const & other) const noexcept override
447ffcd984SEric Fiselier         { return &other == this; }
457ffcd984SEric Fiselier 
467ffcd984SEric Fiselier public:
477ffcd984SEric Fiselier     ~__new_delete_memory_resource_imp() override = default;
4815551efdSEric Fiselier };
4915551efdSEric Fiselier 
5015551efdSEric Fiselier // null_memory_resource()
5115551efdSEric Fiselier 
52e2f2d1edSEric Fiselier class _LIBCPP_TYPE_VIS __null_memory_resource_imp
5315551efdSEric Fiselier     : public memory_resource
5415551efdSEric Fiselier {
5515551efdSEric Fiselier public:
5615551efdSEric Fiselier     ~__null_memory_resource_imp() = default;
5715551efdSEric Fiselier 
5815551efdSEric Fiselier protected:
do_allocate(size_t,size_t)5915551efdSEric Fiselier     virtual void* do_allocate(size_t, size_t) {
60d437fa5cSMarshall Clow         __throw_bad_alloc();
6115551efdSEric Fiselier     }
do_deallocate(void *,size_t,size_t)6215551efdSEric Fiselier     virtual void do_deallocate(void *, size_t, size_t) {}
do_is_equal(memory_resource const & __other) const635601305fSLouis Dionne     virtual bool do_is_equal(memory_resource const & __other) const noexcept
6415551efdSEric Fiselier     { return &__other == this; }
6515551efdSEric Fiselier };
6615551efdSEric Fiselier 
67faaeaaf0SEric Fiselier namespace {
68faaeaaf0SEric Fiselier 
6915551efdSEric Fiselier union ResourceInitHelper {
7015551efdSEric Fiselier   struct {
7115551efdSEric Fiselier     __new_delete_memory_resource_imp new_delete_res;
7215551efdSEric Fiselier     __null_memory_resource_imp       null_res;
7315551efdSEric Fiselier   } resources;
7415551efdSEric Fiselier   char dummy;
ResourceInitHelper()7515551efdSEric Fiselier   _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
~ResourceInitHelper()7615551efdSEric Fiselier   ~ResourceInitHelper() {}
7715551efdSEric Fiselier };
78241d4ad7SEric Fiselier 
79515afe8bSLouis Dionne // Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
80515afe8bSLouis Dionne // attribute with a value that's reserved for the implementation (we're the implementation).
81515afe8bSLouis Dionne #include "memory_resource_init_helper.h"
8215551efdSEric Fiselier 
83faaeaaf0SEric Fiselier } // end namespace
84faaeaaf0SEric Fiselier 
85faaeaaf0SEric Fiselier 
new_delete_resource()865601305fSLouis Dionne memory_resource * new_delete_resource() noexcept {
8715551efdSEric Fiselier     return &res_init.resources.new_delete_res;
8815551efdSEric Fiselier }
8915551efdSEric Fiselier 
null_memory_resource()905601305fSLouis Dionne memory_resource * null_memory_resource() noexcept {
9115551efdSEric Fiselier     return &res_init.resources.null_res;
9215551efdSEric Fiselier }
9315551efdSEric Fiselier 
9415551efdSEric Fiselier // default_memory_resource()
9515551efdSEric Fiselier 
9615551efdSEric Fiselier static memory_resource *
__default_memory_resource(bool set=false,memory_resource * new_res=nullptr)975601305fSLouis Dionne __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept
9815551efdSEric Fiselier {
9915551efdSEric Fiselier #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
10005337a75SArthur O'Dwyer     static constinit atomic<memory_resource*> __res{&res_init.resources.new_delete_res};
10115551efdSEric Fiselier     if (set) {
10215551efdSEric Fiselier         new_res = new_res ? new_res : new_delete_resource();
10315551efdSEric Fiselier         // TODO: Can a weaker ordering be used?
10415551efdSEric Fiselier         return _VSTD::atomic_exchange_explicit(
10524c1ab26SEric Fiselier             &__res, new_res, memory_order_acq_rel);
10615551efdSEric Fiselier     }
10715551efdSEric Fiselier     else {
10815551efdSEric Fiselier         return _VSTD::atomic_load_explicit(
10924c1ab26SEric Fiselier             &__res, memory_order_acquire);
11015551efdSEric Fiselier     }
1112266a8d4SEric Fiselier #elif !defined(_LIBCPP_HAS_NO_THREADS)
11205337a75SArthur O'Dwyer     static constinit memory_resource *res = &res_init.resources.new_delete_res;
11315551efdSEric Fiselier     static mutex res_lock;
11415551efdSEric Fiselier     if (set) {
11515551efdSEric Fiselier         new_res = new_res ? new_res : new_delete_resource();
11615551efdSEric Fiselier         lock_guard<mutex> guard(res_lock);
11715551efdSEric Fiselier         memory_resource * old_res = res;
11815551efdSEric Fiselier         res = new_res;
11915551efdSEric Fiselier         return old_res;
12015551efdSEric Fiselier     } else {
12115551efdSEric Fiselier         lock_guard<mutex> guard(res_lock);
12215551efdSEric Fiselier         return res;
12315551efdSEric Fiselier     }
1242266a8d4SEric Fiselier #else
12505337a75SArthur O'Dwyer     static constinit memory_resource *res = &res_init.resources.new_delete_res;
1262266a8d4SEric Fiselier     if (set) {
1272266a8d4SEric Fiselier         new_res = new_res ? new_res : new_delete_resource();
1282266a8d4SEric Fiselier         memory_resource * old_res = res;
1292266a8d4SEric Fiselier         res = new_res;
1302266a8d4SEric Fiselier         return old_res;
1312266a8d4SEric Fiselier     } else {
1322266a8d4SEric Fiselier         return res;
1332266a8d4SEric Fiselier     }
13415551efdSEric Fiselier #endif
13515551efdSEric Fiselier }
13615551efdSEric Fiselier 
get_default_resource()1375601305fSLouis Dionne memory_resource * get_default_resource() noexcept
13815551efdSEric Fiselier {
13915551efdSEric Fiselier     return __default_memory_resource();
14015551efdSEric Fiselier }
14115551efdSEric Fiselier 
set_default_resource(memory_resource * __new_res)1425601305fSLouis Dionne memory_resource * set_default_resource(memory_resource * __new_res) noexcept
14315551efdSEric Fiselier {
14415551efdSEric Fiselier     return __default_memory_resource(true, __new_res);
14515551efdSEric Fiselier }
14615551efdSEric Fiselier 
14715551efdSEric Fiselier _LIBCPP_END_NAMESPACE_LFTS_PMR
148