xref: /aosp_15_r20/external/pigweed/pw_allocator/public/pw_allocator/pmr_allocator.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 #include "pw_allocator/allocator.h"
17 #include "pw_allocator/config.h"
18 #include "pw_status/status_with_size.h"
19 
20 #if __has_include(<memory_resource>)
21 #include <memory_resource>
22 namespace pw {
23 namespace pmr = ::std::pmr;
24 }  // namespace pw
25 
26 #elif __has_include(<experimental/memory_resource>)
27 #include <experimental/memory_resource>
28 namespace pw {
29 namespace pmr = ::std::experimental::pmr;
30 }  // namespace pw
31 
32 #else
33 #error "<memory_resource> is required to use this header!"
34 #endif  // __has_include(<memory_resource>)
35 
36 namespace pw::allocator {
37 
38 // Forward declaration
39 class PmrAllocator;
40 
41 namespace internal {
42 
43 /// Implementation of C++'s abstract memory resource interface that uses an
44 /// Allocator.
45 ///
46 /// NOTE! This class aborts if allocation fails.
47 ///
48 /// See also https://en.cppreference.com/w/cpp/memory/memory_resource.
49 class MemoryResource final : public pw::pmr::memory_resource {
50  public:
51   constexpr MemoryResource() = default;
52 
allocator()53   Allocator& allocator() { return *allocator_; }
54 
55  private:
56   friend class ::pw::allocator::PmrAllocator;
set_allocator(Allocator & allocator)57   void set_allocator(Allocator& allocator) { allocator_ = &allocator; }
58 
59   void* do_allocate(size_t bytes, size_t alignment) override;
60   void do_deallocate(void* p, size_t bytes, size_t alignment) override;
61   bool do_is_equal(
62       const pw::pmr::memory_resource& other) const noexcept override;
63 
64   Allocator* allocator_ = nullptr;
65 };
66 
67 }  // namespace internal
68 
69 /// Implementation of C++'s abstract polymorphic allocator interface that uses
70 /// a pw::Allocator.
71 ///
72 /// Note that despite is name, this is NOT a pw::Allocator itself. Instead, it
73 /// can be used in `pw::pmr` containers, such as `pw::pmr::vector`.
74 ///
75 /// See also https://en.cppreference.com/w/cpp/memory/polymorphic_allocator.
76 class PmrAllocator final : public pw::pmr::polymorphic_allocator<std::byte> {
77  public:
78   using Base = pw::pmr::polymorphic_allocator<std::byte>;
79 
PmrAllocator(Allocator & allocator)80   explicit PmrAllocator(Allocator& allocator) : Base(&memory_resource_) {
81     memory_resource_.set_allocator(allocator);
82   }
83 
allocator()84   Allocator& allocator() { return memory_resource_.allocator(); }
85 
86  private:
87   internal::MemoryResource memory_resource_;
88 };
89 
90 }  // namespace pw::allocator
91