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);
123 friend class PoisonableBlock;
127template <
typename BlockType>
128struct is_contiguous : std::is_base_of<internal::ContiguousBase, BlockType> {};
131template <
typename BlockType>
142void CheckNextMisaligned(
const void* block,
144 bool next_is_aligned);
148void CheckNextPrevMismatched(
const void* block,
150 const void* next_prev,
151 bool next_prev_matches);
155void CheckPrevMisaligned(
const void* block,
157 bool prev_is_aligned);
161void CheckPrevNextMismatched(
const void* block,
163 const void* prev_next,
164 bool prev_next_matches);
170template <
typename Derived>
172 if constexpr (Hardening::kIncludesDebugChecks) {
173 derived()->CheckInvariants();
175 return PrevUnchecked();
178template <
typename Derived>
180 size_t prev_outer_size = derived()->PrevOuterSizeUnchecked();
181 if (prev_outer_size == 0) {
184 auto addr = cpp20::bit_cast<uintptr_t>(
this);
185 Hardening::Decrement(addr, prev_outer_size);
186 return std::launder(
reinterpret_cast<Derived*
>(addr));
189template <
typename Derived>
191 if constexpr (Hardening::kIncludesDebugChecks) {
192 derived()->CheckInvariants();
194 return NextUnchecked();
197template <
typename Derived>
199 if (derived()->IsLastUnchecked()) {
202 size_t outer_size = derived()->OuterSizeUnchecked();
203 auto addr = cpp20::bit_cast<uintptr_t>(
this);
204 Hardening::Increment(addr, outer_size);
205 return std::launder(
reinterpret_cast<Derived*
>(addr));
208template <
typename Derived>
210 size_t new_inner_size) {
211 Derived* next = derived()->Next();
212 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
213 ByteSpan bytes(derived()->UsableSpace(), derived()->InnerSize());
214 bytes = bytes.subspan(new_inner_size);
215 auto* trailing = Derived::AsBlock(bytes);
216 derived()->SetNext(new_outer_size, trailing);
217 trailing->SetNext(bytes.size(), next);
221template <
typename Derived>
223 size_t new_inner_size) {
224 size_t new_outer_size = Derived::kBlockOverhead + new_inner_size;
225 return DoSplitFirst(derived()->InnerSize() - new_outer_size);
228template <
typename Derived>
230 Derived* next = derived()->Next();
231 if (next !=
nullptr) {
232 size_t outer_size = derived()->OuterSize() + next->OuterSize();
233 derived()->SetNext(outer_size, next->Next());
237template <
typename Derived>
241 Derived* next = derived()->NextUnchecked();
242 if (next !=
nullptr) {
243 valid &= (cpp20::bit_cast<uintptr_t>(next) % Derived::kAlignment) == 0;
244 if constexpr (Hardening::kIncludesDebugChecks) {
245 internal::CheckNextMisaligned(
this, next, valid || !strict);
248 Derived* next_prev = next->PrevUnchecked();
249 valid &=
this == next_prev;
250 if constexpr (Hardening::kIncludesDebugChecks) {
251 internal::CheckNextPrevMismatched(
252 this, next, next_prev, valid || !strict);
256 Derived* prev = derived()->PrevUnchecked();
257 if (prev !=
nullptr) {
258 valid &= (cpp20::bit_cast<uintptr_t>(prev) % Derived::kAlignment) == 0;
259 if constexpr (Hardening::kIncludesDebugChecks) {
260 internal::CheckPrevMisaligned(
this, prev, valid || !strict);
263 Derived* prev_next = prev->NextUnchecked();
264 valid &=
this == prev_next;
265 if constexpr (Hardening::kIncludesDebugChecks) {
266 internal::CheckPrevNextMismatched(
267 this, prev, prev_next, valid || !strict);
Definition: contiguous.h:45
constexpr Derived * Prev() const
Definition: contiguous.h:171
constexpr bool DoCheckInvariants(bool strict) const
Performs the ContiguousBlock invariant checks.
Definition: contiguous.h:238
constexpr Derived * Next() const
Definition: contiguous.h:190
constexpr void DoMergeNext()
Definition: contiguous.h:229
constexpr Derived * DoSplitLast(size_t new_inner_size)
Definition: contiguous.h:222
constexpr Derived * DoSplitFirst(size_t new_inner_size)
Definition: contiguous.h:209
Definition: contiguous.h:25
Trait type that allow interrogating a block as to whether it is contiguous.
Definition: contiguous.h:128