C/C++ API Reference
Loading...
Searching...
No Matches
sequenced.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 <algorithm>
17#include <cstddef>
18#include <iterator>
19
20#include "pw_allocator/bucket/base.h"
21#include "pw_containers/intrusive_list.h"
22
23namespace pw::allocator {
24
26
35 : public containers::future::IntrusiveList<SequencedItem>::Item {};
36
43template <typename BlockType>
44class SequencedBucket : public internal::BucketBase<SequencedBucket<BlockType>,
45 BlockType,
46 SequencedItem> {
47 private:
48 using Base = internal::
49 BucketBase<SequencedBucket<BlockType>, BlockType, SequencedItem>;
50 friend Base;
51
52 public:
54
55 constexpr size_t threshold() const { return threshold_; }
56
63 void set_threshold(size_t threshold) { threshold_ = threshold; }
64
65 private:
67 void DoAdd(BlockType& block) {
68 auto* item_to_add = new (block.UsableSpace()) SequencedItem();
69 containers::future::IntrusiveList<SequencedItem>::iterator iter;
70 if (block.InnerSize() < threshold_) {
71 // Search from back.
72 auto r_iter = std::find_if(
73 items_.rbegin(), items_.rend(), [item_to_add](SequencedItem& item) {
74 return &item < item_to_add;
75 });
76
77 // If r_iter dereferences to the last address that is before than the
78 // item to add, then the corresponding forward iterator points to the
79 // first address that is after the item to add.
80 iter = r_iter.base();
81
82 } else {
83 // Search from front.
84 iter = std::find_if(
85 items_.begin(), items_.end(), [item_to_add](SequencedItem& item) {
86 return item_to_add < &item;
87 });
88 }
89 items_.insert(iter, *item_to_add);
90 }
91
93 const BlockType* DoFindLargest() const {
94 auto iter = std::max_element(items_.begin(), items_.end(), Base::Compare);
95 return BlockType::FromUsableSpace(&(*iter));
96 }
97
99 BlockType* DoRemoveAny() {
100 SequencedItem& item = items_.front();
101 items_.pop_front();
102 return BlockType::FromUsableSpace(&item);
103 }
104
106 bool DoRemove(BlockType& block) {
107 SequencedItem& item_to_remove = Base::GetItemFrom(block);
108 if (block.InnerSize() >= threshold_) {
109 // Search from front and remove.
110 return items_.remove(item_to_remove);
111 }
112 // Search from back and remove.
113 auto iter = std::find_if(
114 items_.rbegin(), items_.rend(), [&item_to_remove](SequencedItem& item) {
115 return &item_to_remove == &item;
116 });
117 if (iter == items_.rend()) {
118 return false;
119 }
120 items_.erase(*iter);
121 return true;
122 }
123
125 BlockType* DoRemoveCompatible(Layout layout) {
126 auto predicate = Base::MakeCanAllocPredicate(layout);
127 SequencedItem* item = nullptr;
128 if (layout.size() < threshold_) {
129 // Search from back.
130 auto iter = std::find_if(items_.rbegin(), items_.rend(), predicate);
131 item = iter != items_.rend() ? &(*iter) : nullptr;
132 } else {
133 // Search from front.
134 auto iter = std::find_if(items_.begin(), items_.end(), predicate);
135 item = iter != items_.end() ? &(*iter) : nullptr;
136 }
137 if (item == nullptr) {
138 return nullptr;
139 }
140 auto* block = BlockType::FromUsableSpace(item);
141 items_.erase(*item);
142 return block;
143 }
144
145 containers::future::IntrusiveList<SequencedItem> items_;
146 size_t threshold_ = 0;
147};
148
150
151} // namespace pw::allocator
Definition: sequenced.h:46
void set_threshold(size_t threshold)
Definition: sequenced.h:63
Definition: sequenced.h:35
static bool Compare(const ItemType &item1, const ItemType &item2)
Definition: base.h:178
void Clear()
Removes all blocks from this bucket.
Definition: base.h:134
Definition: intrusive_list.h:88
SmallBlock BlockType
Default block type to use for tests.
Definition: size_report.h:32