xref: /aosp_15_r20/external/pigweed/pw_allocator/public/pw_allocator/capability.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 <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