C/C++ API Reference
Loading...
Searching...
No Matches
sorted.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
18#include "pw_allocator/bucket/base.h"
19#include "pw_containers/intrusive_forward_list.h"
20
21namespace pw::allocator {
22
24
32class SortedItem : public IntrusiveForwardList<SortedItem>::Item {};
33
34// Forward declarations.
35
36template <typename BlockType>
38
39template <typename BlockType>
41
42namespace internal {
43
54template <typename Derived, typename BlockType>
55class SortedBucketBase : public BucketBase<Derived, BlockType, SortedItem> {
56 public:
58
59 protected:
61 friend Base;
62
63 constexpr SortedBucketBase() = default;
64
65 const IntrusiveForwardList<SortedItem>& items() const { return items_; }
66
68 void DoAdd(BlockType& block);
69
71 BlockType* DoRemoveAny();
72
74 bool DoRemove(BlockType& block) {
75 return items_.remove(Base::GetItemFrom(block));
76 }
77
79 BlockType* DoRemoveCompatible(Layout layout);
80
81 private:
83};
84
85} // namespace internal
86
94template <typename BlockType>
96 : public internal::SortedBucketBase<ForwardSortedBucket<BlockType>,
97 BlockType> {
98 private:
99 using Base =
101
102 friend Base;
103 // Suppress `no uniquely matching class member found` Doxygen error
105 friend typename Base::Base;
107
112 static constexpr auto MakeAddPredicate(size_t inner_size);
113
115 const BlockType* DoFindLargest() const;
116};
117
125template <typename BlockType>
127 : public internal::SortedBucketBase<ReverseSortedBucket<BlockType>,
128 BlockType> {
129 private:
130 using Base =
132
133 friend Base;
134 // Suppress `no uniquely matching class member found` Doxygen error
136 friend typename Base::Base;
138
143 static constexpr auto MakeAddPredicate(size_t inner_size);
144
146 const BlockType* DoFindLargest() const;
147};
148
150
151// Template method implementations.
152
153namespace internal {
154
155template <typename Derived, typename BlockType>
157 auto* item_to_add = new (block.UsableSpace()) SortedItem();
158 auto prev = Base::FindPrevIf(items_.before_begin(),
159 items_.end(),
160 Derived::MakeAddPredicate(block.InnerSize()));
161 items_.insert_after(prev, *item_to_add);
162}
163
164template <typename Derived, typename BlockType>
166 SortedItem& item = items_.front();
167 items_.pop_front();
168 return BlockType::FromUsableSpace(&item);
169}
170
171template <typename Derived, typename BlockType>
173 Layout layout) {
174 auto prev = Base::FindPrevIf(
175 items_.before_begin(), items_.end(), Base::MakeCanAllocPredicate(layout));
176 auto* block = Base::GetBlockFromPrev(prev, items_.end());
177 if (block != nullptr) {
178 items_.erase_after(prev);
179 }
180 return block;
181}
182
183} // namespace internal
184
185template <typename BlockType>
187 size_t inner_size) {
188 return [inner_size](SortedItem& item) {
189 auto* block = BlockType::FromUsableSpace(&item);
190 return inner_size < block->InnerSize();
191 };
192}
193
194template <typename BlockType>
195const BlockType* ForwardSortedBucket<BlockType>::DoFindLargest() const {
196 const auto& items = Base::items();
197 if (items.empty()) {
198 return nullptr;
199 }
200 auto iter = items.before_begin();
201 auto prev = iter;
202 do {
203 prev = iter++;
204 } while (iter != items.end());
205 return BlockType::FromUsableSpace(&(*prev));
206}
207
208template <typename BlockType>
209constexpr auto ReverseSortedBucket<BlockType>::MakeAddPredicate(
210 size_t inner_size) {
211 return [inner_size](SortedItem& item) {
212 auto* block = BlockType::FromUsableSpace(&item);
213 return block->InnerSize() < inner_size;
214 };
215}
216
217template <typename BlockType>
218const BlockType* ReverseSortedBucket<BlockType>::DoFindLargest() const {
219 const auto& items = Base::items();
220 auto iter = items.begin();
221 return BlockType::FromUsableSpace(&(*iter));
222}
223
224} // namespace pw::allocator
Definition: intrusive_forward_list.h:99
Definition: sorted.h:97
Definition: layout.h:64
Definition: sorted.h:128
Definition: sorted.h:32
void Clear()
Removes all blocks from this bucket.
Definition: base.h:118
static ItemType & GetItemFrom(BlockType &block)
Definition: base.h:169
BlockType * DoRemoveCompatible(Layout layout)
Definition: sorted.h:172
bool DoRemove(BlockType &block)
Definition: sorted.h:74
BlockType * DoRemoveAny()
Definition: sorted.h:165
void DoAdd(BlockType &block)
Definition: sorted.h:156
SmallBlock BlockType
Default block type to use for tests.
Definition: size_report.h:32