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