16#include "lib/stdcompat/bit.h"
17#include "pw_allocator/block/basic.h"
18#include "pw_allocator/hardening.h"
19#include "pw_bytes/span.h"
21namespace pw::allocator {
44template <
typename Derived>
52 "Types derived from ContiguousBlock must also derive from BasicBlock");
58 constexpr Derived*
Prev()
const;
62 constexpr Derived*
Next()
const;
99 constexpr Derived* derived() {
return static_cast<Derived*
>(
this); }
100 constexpr const Derived* derived()
const {
101 return static_cast<const Derived*
>(
this);
105 constexpr Derived* PrevUnchecked()
const;
108 constexpr Derived* NextUnchecked()
const;
119 static constexpr Derived* Split(Derived*& block,
size_t new_inner_size);
122 static constexpr ByteSpan AsBytes(Derived*&& block);
126 friend class PoisonableBlock;
130template <
typename BlockType>
131struct is_contiguous : std::is_base_of<internal::ContiguousBase, BlockType> {};
134template <
typename BlockType>
145void CheckNextMisaligned(
const void* block,
147 bool next_is_aligned);
151void CheckNextPrevMismatched(
const void* block,
153 const void* next_prev,
154 bool next_prev_matches);
158void CheckPrevMisaligned(
const void* block,
160 bool prev_is_aligned);
164void CheckPrevNextMismatched(
const void* block,
166 const void* prev_next,
167 bool prev_next_matches);
173template <
typename Derived>
175 if constexpr (Hardening::kIncludesDebugChecks) {
176 derived()->CheckInvariants();
178 return PrevUnchecked();
181template <
typename Derived>
183 size_t prev_outer_size = derived()->PrevOuterSizeUnchecked();
184 if (prev_outer_size == 0) {
187 auto addr = cpp20::bit_cast<uintptr_t>(
this);
188 Hardening::Decrement(addr, prev_outer_size);
189 return std::launder(
reinterpret_cast<Derived*
>(addr));
192template <
typename Derived>
194 if constexpr (Hardening::kIncludesDebugChecks) {
195 derived()->CheckInvariants();
197 return NextUnchecked();
200template <
typename Derived>
202 if (derived()->IsLastUnchecked()) {
205 size_t outer_size = derived()->OuterSizeUnchecked();
206 auto addr = cpp20::bit_cast<uintptr_t>(
this);
207 Hardening::Increment(addr, outer_size);
208 return std::launder(
reinterpret_cast<Derived*
>(addr));
211template <
typename Derived>
213 size_t new_inner_size) {
214 Derived* next = derived()->Next();
215 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
216 ByteSpan bytes(derived()->UsableSpace(), derived()->InnerSize());
217 bytes = bytes.subspan(new_inner_size);
218 auto* trailing = Derived::AsBlock(bytes);
219 derived()->SetNext(new_outer_size, trailing);
220 trailing->SetNext(bytes.size(), next);
224template <
typename Derived>
226 size_t new_inner_size) {
227 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
228 return DoSplitFirst(derived()->InnerSize() - new_outer_size);
231template <
typename Derived>
233 Derived* next = derived()->Next();
234 if (next !=
nullptr) {
235 size_t outer_size = derived()->OuterSize() + next->OuterSize();
236 derived()->SetNext(outer_size, next->Next());
240template <
typename Derived>
244 Derived* next = derived()->NextUnchecked();
245 if (next !=
nullptr) {
246 valid &= (cpp20::bit_cast<uintptr_t>(next) % Derived::kAlignment) == 0;
247 if constexpr (Hardening::kIncludesDebugChecks) {
248 internal::CheckNextMisaligned(
this, next, valid || !strict);
251 Derived* next_prev = next->PrevUnchecked();
252 valid &=
this == next_prev;
253 if constexpr (Hardening::kIncludesDebugChecks) {
254 internal::CheckNextPrevMismatched(
255 this, next, next_prev, valid || !strict);
259 Derived* prev = derived()->PrevUnchecked();
260 if (prev !=
nullptr) {
261 valid &= (cpp20::bit_cast<uintptr_t>(prev) % Derived::kAlignment) == 0;
262 if constexpr (Hardening::kIncludesDebugChecks) {
263 internal::CheckPrevMisaligned(
this, prev, valid || !strict);
266 Derived* prev_next = prev->NextUnchecked();
267 valid &=
this == prev_next;
268 if constexpr (Hardening::kIncludesDebugChecks) {
269 internal::CheckPrevNextMismatched(
270 this, prev, prev_next, valid || !strict);
Definition: contiguous.h:45
constexpr Derived * Prev() const
Definition: contiguous.h:174
constexpr bool DoCheckInvariants(bool strict) const
Performs the ContiguousBlock invariant checks.
Definition: contiguous.h:241
constexpr Derived * Next() const
Definition: contiguous.h:193
constexpr void DoMergeNext()
Definition: contiguous.h:232
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: contiguous.h:225
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: contiguous.h:212
Definition: contiguous.h:25
Trait type that allow interrogating a block as to whether it is contiguous.
Definition: contiguous.h:131