1*4bdff4beSrobert //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick
9*4bdff4beSrobert #include <experimental/memory_resource>
10*4bdff4beSrobert
11*4bdff4beSrobert _LIBCPP_SUPPRESS_DEPRECATED_PUSH
1246035553Spatrick
1346035553Spatrick #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
14*4bdff4beSrobert # include <atomic>
1546035553Spatrick #elif !defined(_LIBCPP_HAS_NO_THREADS)
16*4bdff4beSrobert # include <mutex>
1746035553Spatrick # if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
1846035553Spatrick # pragma comment(lib, "pthread")
1946035553Spatrick # endif
2046035553Spatrick #endif
2146035553Spatrick
2246035553Spatrick _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
2346035553Spatrick
2446035553Spatrick // memory_resource
2546035553Spatrick
2646035553Spatrick //memory_resource::~memory_resource() {}
2746035553Spatrick
2846035553Spatrick // new_delete_resource()
2946035553Spatrick
3046035553Spatrick class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp
3146035553Spatrick : public memory_resource
3246035553Spatrick {
do_allocate(size_t size,size_t align)3346035553Spatrick void *do_allocate(size_t size, size_t align) override {
3446035553Spatrick #ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
3546035553Spatrick if (__is_overaligned_for_new(align))
3646035553Spatrick __throw_bad_alloc();
3746035553Spatrick #endif
3846035553Spatrick return _VSTD::__libcpp_allocate(size, align);
3946035553Spatrick }
4046035553Spatrick
do_deallocate(void * p,size_t n,size_t align)4146035553Spatrick void do_deallocate(void *p, size_t n, size_t align) override {
4246035553Spatrick _VSTD::__libcpp_deallocate(p, n, align);
4346035553Spatrick }
4446035553Spatrick
do_is_equal(memory_resource const & other) const4576d0caaeSpatrick bool do_is_equal(memory_resource const & other) const noexcept override
4646035553Spatrick { return &other == this; }
4746035553Spatrick
4846035553Spatrick public:
4946035553Spatrick ~__new_delete_memory_resource_imp() override = default;
5046035553Spatrick };
5146035553Spatrick
5246035553Spatrick // null_memory_resource()
5346035553Spatrick
5446035553Spatrick class _LIBCPP_TYPE_VIS __null_memory_resource_imp
5546035553Spatrick : public memory_resource
5646035553Spatrick {
5746035553Spatrick public:
5846035553Spatrick ~__null_memory_resource_imp() = default;
5946035553Spatrick
6046035553Spatrick protected:
do_allocate(size_t,size_t)6146035553Spatrick virtual void* do_allocate(size_t, size_t) {
6246035553Spatrick __throw_bad_alloc();
6346035553Spatrick }
do_deallocate(void *,size_t,size_t)6446035553Spatrick virtual void do_deallocate(void *, size_t, size_t) {}
do_is_equal(memory_resource const & __other) const6576d0caaeSpatrick virtual bool do_is_equal(memory_resource const & __other) const noexcept
6646035553Spatrick { return &__other == this; }
6746035553Spatrick };
6846035553Spatrick
6946035553Spatrick namespace {
7046035553Spatrick
7146035553Spatrick union ResourceInitHelper {
7246035553Spatrick struct {
7346035553Spatrick __new_delete_memory_resource_imp new_delete_res;
7446035553Spatrick __null_memory_resource_imp null_res;
7546035553Spatrick } resources;
7646035553Spatrick char dummy;
ResourceInitHelper()77*4bdff4beSrobert _LIBCPP_CONSTEXPR_SINCE_CXX14 ResourceInitHelper() : resources() {}
~ResourceInitHelper()7846035553Spatrick ~ResourceInitHelper() {}
7946035553Spatrick };
8046035553Spatrick
81*4bdff4beSrobert // Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
82*4bdff4beSrobert // attribute with a value that's reserved for the implementation (we're the implementation).
83*4bdff4beSrobert #include "memory_resource_init_helper.h"
8446035553Spatrick
8546035553Spatrick } // end namespace
8646035553Spatrick
8746035553Spatrick
new_delete_resource()8876d0caaeSpatrick memory_resource * new_delete_resource() noexcept {
8946035553Spatrick return &res_init.resources.new_delete_res;
9046035553Spatrick }
9146035553Spatrick
null_memory_resource()9276d0caaeSpatrick memory_resource * null_memory_resource() noexcept {
9346035553Spatrick return &res_init.resources.null_res;
9446035553Spatrick }
9546035553Spatrick
9646035553Spatrick // default_memory_resource()
9746035553Spatrick
9846035553Spatrick static memory_resource *
__default_memory_resource(bool set=false,memory_resource * new_res=nullptr)9976d0caaeSpatrick __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept
10046035553Spatrick {
10146035553Spatrick #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
102*4bdff4beSrobert static constinit atomic<memory_resource*> __res{&res_init.resources.new_delete_res};
10346035553Spatrick if (set) {
10446035553Spatrick new_res = new_res ? new_res : new_delete_resource();
10546035553Spatrick // TODO: Can a weaker ordering be used?
10646035553Spatrick return _VSTD::atomic_exchange_explicit(
10746035553Spatrick &__res, new_res, memory_order_acq_rel);
10846035553Spatrick }
10946035553Spatrick else {
11046035553Spatrick return _VSTD::atomic_load_explicit(
11146035553Spatrick &__res, memory_order_acquire);
11246035553Spatrick }
11346035553Spatrick #elif !defined(_LIBCPP_HAS_NO_THREADS)
114*4bdff4beSrobert static constinit memory_resource *res = &res_init.resources.new_delete_res;
11546035553Spatrick static mutex res_lock;
11646035553Spatrick if (set) {
11746035553Spatrick new_res = new_res ? new_res : new_delete_resource();
11846035553Spatrick lock_guard<mutex> guard(res_lock);
11946035553Spatrick memory_resource * old_res = res;
12046035553Spatrick res = new_res;
12146035553Spatrick return old_res;
12246035553Spatrick } else {
12346035553Spatrick lock_guard<mutex> guard(res_lock);
12446035553Spatrick return res;
12546035553Spatrick }
12646035553Spatrick #else
127*4bdff4beSrobert static constinit memory_resource *res = &res_init.resources.new_delete_res;
12846035553Spatrick if (set) {
12946035553Spatrick new_res = new_res ? new_res : new_delete_resource();
13046035553Spatrick memory_resource * old_res = res;
13146035553Spatrick res = new_res;
13246035553Spatrick return old_res;
13346035553Spatrick } else {
13446035553Spatrick return res;
13546035553Spatrick }
13646035553Spatrick #endif
13746035553Spatrick }
13846035553Spatrick
get_default_resource()13976d0caaeSpatrick memory_resource * get_default_resource() noexcept
14046035553Spatrick {
14146035553Spatrick return __default_memory_resource();
14246035553Spatrick }
14346035553Spatrick
set_default_resource(memory_resource * __new_res)14476d0caaeSpatrick memory_resource * set_default_resource(memory_resource * __new_res) noexcept
14546035553Spatrick {
14646035553Spatrick return __default_memory_resource(true, __new_res);
14746035553Spatrick }
14846035553Spatrick
14946035553Spatrick _LIBCPP_END_NAMESPACE_LFTS_PMR
150