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>
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);
123 friend class PoisonableBlock;
127template <
typename BlockType>
128struct is_contiguous : std::is_base_of<internal::ContiguousBase, BlockType> {};
131template <
typename BlockType>
144void CheckNextMisaligned(
const void* block,
146 bool next_is_aligned);
150void CheckNextPrevMismatched(
const void* block,
152 const void* next_prev,
153 bool next_prev_matches);
157void CheckPrevMisaligned(
const void* block,
159 bool prev_is_aligned);
163void CheckPrevNextMismatched(
const void* block,
165 const void* prev_next,
166 bool prev_next_matches);
172template <
typename Derived>
174 if constexpr (Hardening::kIncludesDebugChecks) {
175 derived()->CheckInvariants();
177 return PrevUnchecked();
180template <
typename Derived>
182 size_t prev_outer_size = derived()->PrevOuterSizeUnchecked();
183 if (prev_outer_size == 0) {
186 auto addr = cpp20::bit_cast<uintptr_t>(
this);
187 Hardening::Decrement(addr, prev_outer_size);
188 return std::launder(
reinterpret_cast<Derived*
>(addr));
191template <
typename Derived>
193 if constexpr (Hardening::kIncludesDebugChecks) {
194 derived()->CheckInvariants();
196 return NextUnchecked();
199template <
typename Derived>
201 if (derived()->IsLastUnchecked()) {
204 size_t outer_size = derived()->OuterSizeUnchecked();
205 auto addr = cpp20::bit_cast<uintptr_t>(
this);
206 Hardening::Increment(addr, outer_size);
207 return std::launder(
reinterpret_cast<Derived*
>(addr));
210template <
typename Derived>
212 size_t new_inner_size) {
213 Derived* next = derived()->Next();
214 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
215 ByteSpan bytes(derived()->UsableSpace(), derived()->InnerSize());
216 bytes = bytes.subspan(new_inner_size);
217 auto* trailing = Derived::AsBlock(bytes);
218 derived()->SetNext(new_outer_size, trailing);
219 trailing->SetNext(bytes.size(), next);
223template <
typename Derived>
225 size_t new_inner_size) {
226 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
227 return DoSplitFirst(derived()->InnerSize() - new_outer_size);
230template <
typename Derived>
232 Derived* next = derived()->Next();
233 if (next !=
nullptr) {
234 size_t outer_size = derived()->OuterSize() + next->OuterSize();
235 derived()->SetNext(outer_size, next->Next());
239template <
typename Derived>
243 Derived* next = derived()->NextUnchecked();
244 if (next !=
nullptr) {
245 valid &= (cpp20::bit_cast<uintptr_t>(next) % Derived::kAlignment) == 0;
246 if constexpr (Hardening::kIncludesDebugChecks) {
247 internal::CheckNextMisaligned(
this, next, valid || !strict);
250 Derived* next_prev = next->PrevUnchecked();
251 valid &=
this == next_prev;
252 if constexpr (Hardening::kIncludesDebugChecks) {
253 internal::CheckNextPrevMismatched(
254 this, next, next_prev, valid || !strict);
258 Derived* prev = derived()->PrevUnchecked();
259 if (prev !=
nullptr) {
260 valid &= (cpp20::bit_cast<uintptr_t>(prev) % Derived::kAlignment) == 0;
261 if constexpr (Hardening::kIncludesDebugChecks) {
262 internal::CheckPrevMisaligned(
this, prev, valid || !strict);
265 Derived* prev_next = prev->NextUnchecked();
266 valid &=
this == prev_next;
267 if constexpr (Hardening::kIncludesDebugChecks) {
268 internal::CheckPrevNextMismatched(
269 this, prev, prev_next, valid || !strict);
Definition: contiguous.h:47
constexpr Derived * Prev() const
Definition: contiguous.h:173
constexpr bool DoCheckInvariants(bool strict) const
Performs the ContiguousBlock invariant checks.
Definition: contiguous.h:240
constexpr Derived * Next() const
Definition: contiguous.h:192
constexpr void DoMergeNext()
Definition: contiguous.h:231
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: contiguous.h:224
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: contiguous.h:211
constexpr bool is_contiguous_v
Helper variable template for is_contiguous<BlockType>::value.
Definition: contiguous.h:132
Definition: contiguous.h:25
Trait type that allow interrogating a block as to whether it is contiguous.
Definition: contiguous.h:128