Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
base.h
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 <cstddef>
17#include <limits>
18
19#include "pw_allocator/block/poisonable.h"
20#include "pw_allocator/config.h"
21#include "pw_allocator/hardening.h"
22#include "pw_allocator/layout.h"
23#include "pw_assert/assert.h"
24#include "pw_bytes/alignment.h"
25
26namespace pw::allocator::internal {
27
54template <typename Derived, typename BlockType_, typename ItemType_>
56 public:
57 using BlockType = BlockType_;
58 using ItemType = ItemType_;
59
60 constexpr BucketBase() {
61 if constexpr (is_poisonable_v<BlockType>) {
62 static_assert(BlockType::kPoisonOffset >= sizeof(ItemType),
63 "Block type does not reserve sufficient space for an item");
64 }
65 }
66
68 constexpr bool empty() const { return derived()->items_.empty(); }
69
71 constexpr size_t max_inner_size() const { return max_inner_size_; }
72
76 constexpr void set_max_inner_size(size_t max_inner_size) {
77 if constexpr (Hardening::kIncludesDebugChecks) {
78 PW_ASSERT(empty());
79 }
80 max_inner_size_ = max_inner_size;
81 }
82
87 [[nodiscard]] bool Add(BlockType& block) {
88 if (block.InnerSize() < sizeof(ItemType)) {
89 return false;
90 }
91 if constexpr (Hardening::kIncludesDebugChecks) {
92 PW_ASSERT(block.InnerSize() <= max_inner_size_);
93 PW_ASSERT(IsAlignedAs<ItemType>(block.UsableSpace()));
94 }
95 derived()->DoAdd(block);
96 return true;
97 }
98
102 [[nodiscard]] BlockType* RemoveAny() {
103 return empty() ? nullptr : derived()->DoRemoveAny();
104 }
105
110 [[nodiscard]] bool Remove(BlockType& block) {
111 return block.InnerSize() >= sizeof(ItemType) && derived()->DoRemove(block);
112 }
113
121 [[nodiscard]] BlockType* RemoveCompatible(Layout layout) {
122 return derived()->DoRemoveCompatible(layout);
123 }
124
126 void Clear() { derived()->items_.clear(); }
127
139 template <typename Iterator, typename Predicate>
140 static Iterator FindPrevIf(Iterator before_first,
141 Iterator last,
142 Predicate predicate) {
143 Iterator prev = before_first;
144 Iterator iter = prev;
145 ++iter;
146 for (; iter != last; ++iter) {
147 if (predicate(*iter)) {
148 break;
149 }
150 prev = iter;
151 }
152 return prev;
153 }
154
159 static auto MakeCanAllocPredicate(Layout layout) {
160 return [layout](ItemType& item) {
161 auto* block = BlockType::FromUsableSpace(&item);
162 return block->CanAlloc(layout).ok();
163 };
164 }
165
168 template <typename Iterator>
169 constexpr BlockType* GetBlockFromIterator(Iterator iter, Iterator last) {
170 return iter != last ? BlockType::FromUsableSpace(&(*iter)) : nullptr;
171 }
172
175 template <typename Iterator>
176 constexpr BlockType* GetBlockFromPrev(Iterator prev, Iterator last) {
177 return GetBlockFromIterator(++prev, last);
178 }
179
180 protected:
187 static ItemType& GetItemFrom(BlockType& block) {
188 return *(std::launder(reinterpret_cast<ItemType*>(block.UsableSpace())));
189 }
190
191 private:
192 constexpr Derived* derived() { return static_cast<Derived*>(this); }
193 constexpr const Derived* derived() const {
194 return static_cast<const Derived*>(this);
195 }
196
198 size_t max_inner_size_ = std::numeric_limits<size_t>::max();
199};
200
205template <typename T, typename U = size_t>
206constexpr U CountRZero(T t) {
207 return static_cast<U>(cpp20::countr_zero(t));
208}
209
214template <typename T, typename U = size_t>
215constexpr U CountLZero(T t) {
216 return static_cast<U>(cpp20::countl_zero(t));
217}
218
219} // namespace pw::allocator::internal
Definition: layout.h:56
constexpr void set_max_inner_size(size_t max_inner_size)
Definition: base.h:76
constexpr BlockType * GetBlockFromIterator(Iterator iter, Iterator last)
Definition: base.h:169
bool Remove(BlockType &block)
Definition: base.h:110
constexpr size_t max_inner_size() const
Returns the configured maximum inner size for blocks in this bucket.
Definition: base.h:71
BlockType * RemoveAny()
Definition: base.h:102
static auto MakeCanAllocPredicate(Layout layout)
Definition: base.h:159
constexpr BlockType * GetBlockFromPrev(Iterator prev, Iterator last)
Definition: base.h:176
void Clear()
Removes all blocks from this bucket.
Definition: base.h:126
static ItemType & GetItemFrom(BlockType &block)
Definition: base.h:187
bool Add(BlockType &block)
Definition: base.h:87
static Iterator FindPrevIf(Iterator before_first, Iterator last, Predicate predicate)
Definition: base.h:140
constexpr bool empty() const
Returns whether this buckets contains any free blocks.
Definition: base.h:68
BlockType * RemoveCompatible(Layout layout)
Definition: base.h:121