C/C++ API Reference
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
29
56template <typename Derived, typename BlockType_, typename ItemType_>
58 public:
59 using BlockType = BlockType_;
60 using ItemType = ItemType_;
61
62 constexpr BucketBase();
63
65 [[nodiscard]] constexpr bool empty() const {
66 return derived()->items_.empty();
67 }
68
70 [[nodiscard]] constexpr size_t max_inner_size() const {
71 return max_inner_size_;
72 }
73
77 constexpr void set_max_inner_size(size_t max_inner_size);
78
83 [[nodiscard]] bool Add(BlockType& block);
84
87 [[nodiscard]] const BlockType* FindLargest() const {
88 return empty() ? nullptr : derived()->DoFindLargest();
89 }
90
94 [[nodiscard]] BlockType* RemoveAny() {
95 return empty() ? nullptr : derived()->DoRemoveAny();
96 }
97
102 [[nodiscard]] bool Remove(BlockType& block) {
103 return block.InnerSize() >= sizeof(ItemType) && derived()->DoRemove(block);
104 }
105
113 [[nodiscard]] BlockType* RemoveCompatible(Layout layout) {
114 return derived()->DoRemoveCompatible(layout);
115 }
116
118 void Clear() { derived()->items_.clear(); }
119
120 protected:
133 template <typename Iterator, typename Predicate>
134 static Iterator FindPrevIf(Iterator before_first,
135 Iterator last,
136 Predicate predicate);
137
142 static auto MakeCanAllocPredicate(Layout layout);
143
146 static bool Compare(const ItemType& item1, const ItemType& item2);
147
150 template <typename Iterator>
151 constexpr static BlockType* GetBlockFromIterator(Iterator iter,
152 Iterator last) {
153 return iter != last ? BlockType::FromUsableSpace(&(*iter)) : nullptr;
154 }
155
158 template <typename Iterator>
159 constexpr static BlockType* GetBlockFromPrev(Iterator prev, Iterator last) {
160 return GetBlockFromIterator(++prev, last);
161 }
162
169 static ItemType& GetItemFrom(BlockType& block) {
170 return *(std::launder(reinterpret_cast<ItemType*>(block.UsableSpace())));
171 }
172
173 private:
174 constexpr Derived* derived() { return static_cast<Derived*>(this); }
175 constexpr const Derived* derived() const {
176 return static_cast<const Derived*>(this);
177 }
178
180 size_t max_inner_size_ = std::numeric_limits<size_t>::max();
181};
182
187template <typename T, typename U = size_t>
188constexpr U CountRZero(T t) {
189 return static_cast<U>(cpp20::countr_zero(t));
190}
191
196template <typename T, typename U = size_t>
197constexpr U CountLZero(T t) {
198 return static_cast<U>(cpp20::countl_zero(t));
199}
200
202
203// Template method implementations.
204
205template <typename Derived, typename BlockType, typename ItemType>
206constexpr BucketBase<Derived, BlockType, ItemType>::BucketBase() {
207 if constexpr (is_poisonable_v<BlockType>) {
208 static_assert(BlockType::kPoisonOffset >= sizeof(ItemType),
209 "Block type does not reserve sufficient space for an item");
210 }
211}
212
213template <typename Derived, typename BlockType, typename ItemType>
215 size_t max_inner_size) {
216 if constexpr (Hardening::kIncludesDebugChecks) {
217 PW_ASSERT(empty());
218 }
219 max_inner_size_ = max_inner_size;
220}
221
222template <typename Derived, typename BlockType, typename ItemType>
224 if (block.InnerSize() < sizeof(ItemType)) {
225 return false;
226 }
227 if constexpr (Hardening::kIncludesDebugChecks) {
228 PW_ASSERT(block.InnerSize() <= max_inner_size_);
229 PW_ASSERT(IsAlignedAs<ItemType>(block.UsableSpace()));
230 }
231 derived()->DoAdd(block);
232 return true;
233}
234
235template <typename Derived, typename BlockType, typename ItemType>
236template <typename Iterator, typename Predicate>
238 Iterator before_first, Iterator last, Predicate predicate) {
239 Iterator prev = before_first;
240 Iterator iter = prev;
241 ++iter;
242 for (; iter != last; ++iter) {
243 if (predicate(*iter)) {
244 break;
245 }
246 prev = iter;
247 }
248 return prev;
249}
250
251template <typename Derived, typename BlockType, typename ItemType>
253 Layout layout) {
254 return [layout](ItemType& item) {
255 auto* block = BlockType::FromUsableSpace(&item);
256 return block->CanAlloc(layout).ok();
257 };
258}
259
260template <typename Derived, typename BlockType, typename ItemType>
262 const ItemType& item2) {
263 const BlockType* block1 = BlockType::FromUsableSpace(&item1);
264 const BlockType* block2 = BlockType::FromUsableSpace(&item2);
265 return block1->InnerSize() < block2->InnerSize();
266}
267
268} // namespace pw::allocator::internal
Definition: fast_sorted.h:35
Definition: layout.h:64
static constexpr BlockType * GetBlockFromPrev(Iterator prev, Iterator last)
Definition: base.h:159
bool Add(BlockType &block)
Definition: base.h:223
static bool Compare(const ItemType &item1, const ItemType &item2)
Definition: base.h:261
bool Remove(BlockType &block)
Definition: base.h:102
static Iterator FindPrevIf(Iterator before_first, Iterator last, Predicate predicate)
Definition: base.h:237
constexpr size_t max_inner_size() const
Returns the configured maximum inner size for blocks in this bucket.
Definition: base.h:70
BlockType * RemoveAny()
Definition: base.h:94
constexpr void set_max_inner_size(size_t max_inner_size)
Definition: base.h:214
const BlockType * FindLargest() const
Definition: base.h:87
void Clear()
Removes all blocks from this bucket.
Definition: base.h:118
static ItemType & GetItemFrom(BlockType &block)
Definition: base.h:169
static constexpr BlockType * GetBlockFromIterator(Iterator iter, Iterator last)
Definition: base.h:151
static auto MakeCanAllocPredicate(Layout layout)
Definition: base.h:252
constexpr bool empty() const
Returns whether this buckets contains any free blocks.
Definition: base.h:65
BlockType * RemoveCompatible(Layout layout)
Definition: base.h:113
constexpr U CountRZero(T t)
Definition: base.h:188
constexpr U CountLZero(T t)
Definition: base.h:197