1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #if __has_include(<memory_resource>) 17 #include <memory_resource> 18 namespace pw { 19 namespace pmr = ::std::pmr; 20 } // namespace pw 21 22 #elif __has_include(<experimental/memory_resource>) 23 #include <experimental/memory_resource> 24 namespace pw { 25 namespace pmr = ::std::experimental::pmr; 26 } // namespace pw 27 28 #else 29 #error "<memory_resource> is required to use this header!" 30 #endif // __has_include(<memory_resource>) 31 32 #include "pw_status/status_with_size.h" 33 34 namespace pw { 35 36 // Forward declaration 37 class Allocator; 38 39 namespace allocator { 40 41 // Forward declaration 42 class AsPmrAllocator; 43 44 namespace internal { 45 46 /// Implementation of C++'s abstract memory resource interface that uses an 47 /// Allocator. 48 /// 49 /// NOTE! This class aborts if allocation fails. 50 /// 51 /// See also https://en.cppreference.com/w/cpp/memory/memory_resource. 52 class MemoryResource final : public pw::pmr::memory_resource { 53 public: 54 constexpr MemoryResource() = default; 55 allocator()56 Allocator& allocator() { return *allocator_; } 57 58 private: 59 friend class ::pw::allocator::AsPmrAllocator; set_allocator(Allocator & allocator)60 void set_allocator(Allocator& allocator) { allocator_ = &allocator; } 61 62 void* do_allocate(size_t bytes, size_t alignment) override; 63 void do_deallocate(void* p, size_t bytes, size_t alignment) override; 64 bool do_is_equal( 65 const pw::pmr::memory_resource& other) const noexcept override; 66 67 Allocator* allocator_ = nullptr; 68 }; 69 70 } // namespace internal 71 72 /// Implementation of C++'s abstract polymorphic allocator interface that uses 73 /// a pw::Allocator. 74 /// 75 /// Note that despite is name, this is NOT a pw::Allocator itself. Instead, it 76 /// can be used in `pw::pmr` containers, such as `pw::pmr::vector`. 77 /// 78 /// See also https://en.cppreference.com/w/cpp/memory/polymorphic_allocator. 79 class AsPmrAllocator final : public pw::pmr::polymorphic_allocator<std::byte> { 80 public: 81 using Base = pw::pmr::polymorphic_allocator<std::byte>; 82 AsPmrAllocator(Allocator & allocator)83 AsPmrAllocator(Allocator& allocator) : Base(&memory_resource_) { 84 memory_resource_.set_allocator(allocator); 85 } 86 allocator()87 Allocator& allocator() { return memory_resource_.allocator(); } 88 89 private: 90 internal::MemoryResource memory_resource_; 91 }; 92 93 } // namespace allocator 94 } // namespace pw 95