Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
simple_allocator.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 "pw_allocator/allocator.h"
17#include "pw_containers/intrusive_list.h"
18#include "pw_multibuf/allocator.h"
19#include "pw_multibuf/config.h"
20#include "pw_multibuf/multibuf_v1.h"
21
22namespace pw::multibuf {
23
24class SimpleAllocator;
25
26namespace internal {
27
30class PW_MULTIBUF_DEPRECATED LinkedRegionTracker final
31 : public ChunkRegionTracker,
32 public IntrusiveList<LinkedRegionTracker>::Item {
33 public:
34 LinkedRegionTracker(SimpleAllocator& parent, ByteSpan region)
35 : parent_(parent), region_(region) {}
37
38 // LinkedRegionTracker is not copyable nor movable.
40 LinkedRegionTracker& operator=(const LinkedRegionTracker&) = delete;
42 LinkedRegionTracker& operator=(LinkedRegionTracker&&) = delete;
43
44 protected:
45 void Destroy() final;
46 ByteSpan Region() const final { return region_; }
47 void* AllocateChunkClass() final;
48 void DeallocateChunkClass(void*) final;
49
50 private:
51 SimpleAllocator& parent_;
52 const ByteSpan region_;
53
54 friend class ::pw::multibuf::SimpleAllocator;
55};
56
57} // namespace internal
58
60class PW_MULTIBUF_DEPRECATED SimpleAllocator : public MultiBufAllocator {
61 public:
76 SimpleAllocator(ByteSpan data_area,
77 pw::allocator::Allocator& metadata_alloc,
78 size_t alignment = 1);
79
80 private:
81 pw::Result<MultiBuf> DoAllocate(
82 size_t min_size,
83 size_t desired_size,
84 ContiguityRequirement contiguity_requirement) final;
85
86 std::optional<size_t> DoGetBackingCapacity() final {
87 return data_area_.size();
88 }
89
91 pw::Result<MultiBuf> InternalAllocateContiguous(size_t size)
92 PW_EXCLUSIVE_LOCKS_REQUIRED(lock_);
93
99 struct FreeBlock final {
103 IntrusiveList<internal::LinkedRegionTracker>::iterator iter;
104
106 ByteSpan span;
107 };
108
109 pw::Result<OwnedChunk> InsertRegion(const FreeBlock&)
110 PW_EXCLUSIVE_LOCKS_REQUIRED(lock_);
111
113 struct AvailableMemorySize final {
115 size_t total;
117 size_t contiguous;
118 };
119
122 AvailableMemorySize GetAvailableMemorySize()
123 PW_EXCLUSIVE_LOCKS_REQUIRED(lock_);
124
126 enum class ControlFlow {
127 Continue,
128 Break,
129 };
130
136 template <typename Fn>
137 void ForEachFreeBlock(Fn function) PW_EXCLUSIVE_LOCKS_REQUIRED(lock_) {
138 std::byte* last_used_end = data_area_.data();
139 // We need to track only the `prev_iter` in order to ensure that we don't
140 // miss any blocks that ``function`` inserts.
141 auto prev_iter = regions_.before_begin();
142 while (true) {
143 // Compute ``cur_iter`` by incrementing ``prev_iter``.
144 auto cur_iter = prev_iter;
145 cur_iter++;
146 if (cur_iter == regions_.end()) {
147 break;
148 }
149 size_t unused =
150 static_cast<size_t>(cur_iter->region_.data() - last_used_end);
151 if (unused != 0) {
152 ControlFlow cf = function({prev_iter, ByteSpan(last_used_end, unused)});
153 if (cf == ControlFlow::Break) {
154 return;
155 }
156 }
157 last_used_end = cur_iter->region_.data() + cur_iter->region_.size();
158 prev_iter = cur_iter;
159 }
160 size_t unused = static_cast<size_t>(
161 (data_area_.data() + data_area_.size()) - last_used_end);
162 if (unused != 0) {
163 function({prev_iter, ByteSpan(last_used_end, unused)});
164 }
165 }
166
167 pw::sync::Mutex lock_;
168 IntrusiveList<internal::LinkedRegionTracker> regions_ PW_GUARDED_BY(lock_);
169 pw::allocator::Allocator& metadata_alloc_;
170 const ByteSpan data_area_;
171 const size_t alignment_;
172
173 friend class internal::LinkedRegionTracker;
174};
175
176} // namespace pw::multibuf
Definition: allocator.h:34
Definition: intrusive_list.h:82
Definition: chunk.h:272
Definition: allocator.h:55
A simple first-fit MultiBufAllocator.
Definition: simple_allocator.h:60
SimpleAllocator(ByteSpan data_area, pw::allocator::Allocator &metadata_alloc, size_t alignment=1)
pw::Result< MultiBuf > DoAllocate(size_t min_size, size_t desired_size, ContiguityRequirement contiguity_requirement) final
std::optional< size_t > DoGetBackingCapacity() final
Definition: simple_allocator.h:86
Definition: simple_allocator.h:32
Definition: mutex.h:42
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27