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 <cstdint> 17 18 #include "pw_assert/assert.h" 19 20 namespace pw::allocator { 21 22 /// Hints about optional methods implemented or optional behaviors requested 23 /// by an allocator of a derived type. 24 /// 25 /// Implementations can provide hints by passing capabilities to the base 26 /// class constructor. These capabilities can be constructed by combining 27 /// ``Capability``s using logical operations. 28 enum Capability : uint32_t { 29 // clang-format off 30 kImplementsGetRequestedLayout = 1 << 0, 31 kImplementsGetUsableLayout = 1 << 1, 32 kImplementsGetAllocatedLayout = 1 << 2, 33 kImplementsGetCapacity = 1 << 4, 34 kImplementsRecognizes = 1 << 5, 35 kSkipsDestroy = 1 << 6, 36 // clang-format on 37 }; 38 39 /// A collection of ``Capability``s. 40 /// 41 /// Concrete allocators should declare a constant set of capabilities, and pass 42 /// it to the ``Allocator`` constructor. 43 /// 44 /// @code{.cpp} 45 /// class MyConcreteAllocator : public Allocator { 46 /// public: 47 /// static constexpr Capabilities kCapabilities = kCapability1 | kCapability2; 48 /// 49 /// MyConcreteAllocator() : Allocator(kCapabilities) {} 50 /// }; 51 /// @endcode 52 /// 53 /// Forwarding allocators should pass the underlying allocator's capabilities, 54 /// potentially with modifications: 55 /// 56 /// @code{.cpp} 57 /// class MyForwardingAllocator : public Allocator { 58 /// public: 59 /// MyForwardingAllocator(Allocator& allocator) 60 /// : Allocator(allocator.capabilities() | kCapability3), 61 /// allocator_(allocator) {} 62 /// }; 63 /// @endcode 64 class Capabilities { 65 public: Capabilities()66 constexpr Capabilities() : capabilities_(0) {} Capabilities(uint32_t capabilities)67 constexpr Capabilities(uint32_t capabilities) : capabilities_(capabilities) {} 68 has(Capability capability)69 constexpr bool has(Capability capability) const { 70 return (capabilities_ & capability) == capability; 71 } 72 get()73 constexpr uint32_t get() const { return capabilities_; } 74 75 private: 76 const uint32_t capabilities_; 77 }; 78 79 inline constexpr bool operator==(const Capabilities& lhs, 80 const Capabilities& rhs) { 81 return lhs.get() == rhs.get(); 82 } 83 84 inline constexpr bool operator!=(const Capabilities& lhs, 85 const Capabilities& rhs) { 86 return lhs.get() != rhs.get(); 87 } 88 89 inline constexpr Capabilities operator|(const Capabilities& lhs, 90 const Capabilities& rhs) { 91 return Capabilities(lhs.get() | rhs.get()); 92 } 93 94 inline constexpr Capabilities operator&(const Capabilities& lhs, 95 const Capabilities& rhs) { 96 return Capabilities(lhs.get() & rhs.get()); 97 } 98 99 inline constexpr Capabilities operator^(const Capabilities& lhs, 100 const Capabilities& rhs) { 101 return Capabilities(lhs.get() ^ rhs.get()); 102 } 103 104 } // namespace pw::allocator 105