xref: /openbsd-src/gnu/llvm/libcxx/src/experimental/memory_resource.cpp (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
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