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 {
46template <
typename Derived>
54 "Types derived from ContiguousBlock must also derive from BasicBlock");
60 constexpr Derived*
Prev()
const;
64 constexpr Derived*
Next()
const;
101 constexpr Derived* derived() {
return static_cast<Derived*
>(
this); }
102 constexpr const Derived* derived()
const {
103 return static_cast<const Derived*
>(
this);
107 constexpr Derived* PrevUnchecked()
const;
110 constexpr Derived* NextUnchecked()
const;
121 static constexpr Derived* Split(Derived*& block,
size_t new_inner_size);
125 friend class PoisonableBlock;
129template <
typename BlockType>
130struct is_contiguous : std::is_base_of<internal::ContiguousBase, BlockType> {};
133template <
typename BlockType>
146void CheckNextMisaligned(
const void* block,
148 bool next_is_aligned);
152void CheckNextPrevMismatched(
const void* block,
154 const void* next_prev,
155 bool next_prev_matches);
159void CheckPrevMisaligned(
const void* block,
161 bool prev_is_aligned);
165void CheckPrevNextMismatched(
const void* block,
167 const void* prev_next,
168 bool prev_next_matches);
174template <
typename Derived>
176 if constexpr (Hardening::kIncludesDebugChecks) {
177 derived()->CheckInvariants();
179 return PrevUnchecked();
182template <
typename Derived>
184 size_t prev_outer_size = derived()->PrevOuterSizeUnchecked();
185 if (prev_outer_size == 0) {
188 auto addr = cpp20::bit_cast<uintptr_t>(
this);
189 Hardening::Decrement(addr, prev_outer_size);
190 return std::launder(
reinterpret_cast<Derived*
>(addr));
193template <
typename Derived>
195 if constexpr (Hardening::kIncludesDebugChecks) {
196 derived()->CheckInvariants();
198 return NextUnchecked();
201template <
typename Derived>
203 if (derived()->IsLastUnchecked()) {
206 size_t outer_size = derived()->OuterSizeUnchecked();
207 auto addr = cpp20::bit_cast<uintptr_t>(
this);
208 Hardening::Increment(addr, outer_size);
209 return std::launder(
reinterpret_cast<Derived*
>(addr));
212template <
typename Derived>
214 size_t new_inner_size) {
215 Derived* next = derived()->Next();
216 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
217 ByteSpan bytes(derived()->UsableSpace(), derived()->InnerSize());
218 bytes = bytes.subspan(new_inner_size);
219 auto* trailing = Derived::AsBlock(bytes);
220 derived()->SetNext(new_outer_size, trailing);
221 trailing->SetNext(bytes.size(), next);
225template <
typename Derived>
227 size_t new_inner_size) {
228 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
229 return DoSplitFirst(derived()->InnerSize() - new_outer_size);
232template <
typename Derived>
234 Derived* next = derived()->Next();
235 if (next !=
nullptr) {
236 size_t outer_size = derived()->OuterSize() + next->OuterSize();
237 derived()->SetNext(outer_size, next->Next());
241template <
typename Derived>
245 Derived* next = derived()->NextUnchecked();
246 if (next !=
nullptr) {
247 valid &= (cpp20::bit_cast<uintptr_t>(next) % Derived::kAlignment) == 0;
248 if constexpr (Hardening::kIncludesDebugChecks) {
249 internal::CheckNextMisaligned(
this, next, valid || !strict);
252 Derived* next_prev = next->PrevUnchecked();
253 valid &=
this == next_prev;
254 if constexpr (Hardening::kIncludesDebugChecks) {
255 internal::CheckNextPrevMismatched(
256 this, next, next_prev, valid || !strict);
260 Derived* prev = derived()->PrevUnchecked();
261 if (prev !=
nullptr) {
262 valid &= (cpp20::bit_cast<uintptr_t>(prev) % Derived::kAlignment) == 0;
263 if constexpr (Hardening::kIncludesDebugChecks) {
264 internal::CheckPrevMisaligned(
this, prev, valid || !strict);
267 Derived* prev_next = prev->NextUnchecked();
268 valid &=
this == prev_next;
269 if constexpr (Hardening::kIncludesDebugChecks) {
270 internal::CheckPrevNextMismatched(
271 this, prev, prev_next, valid || !strict);
Definition: contiguous.h:47
constexpr Derived * Prev() const
Definition: contiguous.h:175
constexpr bool DoCheckInvariants(bool strict) const
Performs the ContiguousBlock invariant checks.
Definition: contiguous.h:242
constexpr Derived * Next() const
Definition: contiguous.h:194
constexpr void DoMergeNext()
Definition: contiguous.h:233
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: contiguous.h:226
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: contiguous.h:213
constexpr bool is_contiguous_v
Helper variable template for is_contiguous<BlockType>::value.
Definition: contiguous.h:134
Definition: contiguous.h:25
Trait type that allow interrogating a block as to whether it is contiguous.
Definition: contiguous.h:130