aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraarongreen <aarongreen@google.com>2023-11-09 16:22:58 +0000
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-11-09 16:22:58 +0000
commit023d64acda3b9750da4514ec6ff41ace9aeeb346 (patch)
treeaf4d6a14d3e6f93b6fe9fe2c533f753d7bce4175
parent09c9783126f13241f88949e1f430c1ace830b916 (diff)
downloadpigweed-023d64acda3b9750da4514ec6ff41ace9aeeb346.tar.gz
pw_allocator: Update interface based on final SEED-0110 design
This CL removes the `...Unchecked` methods from `pw::allocator::Allocator`, and modifies the NVI-style `Do...` methods to take `Layout` parameters. Change-Id: I48de73933ea18ae75dbadb1287780c54fe29873b Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/176754 Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> Commit-Queue: Aaron Green <aarongreen@google.com> Reviewed-by: Taylor Cramer <cramertj@google.com>
-rw-r--r--pw_allocator/allocator.cc15
-rw-r--r--pw_allocator/allocator_metric_proxy.cc33
-rw-r--r--pw_allocator/allocator_test.cc5
-rw-r--r--pw_allocator/allocator_testing.cc27
-rw-r--r--pw_allocator/fallback_allocator.cc35
-rw-r--r--pw_allocator/libc_allocator.cc19
-rw-r--r--pw_allocator/libc_allocator_test.cc2
-rw-r--r--pw_allocator/null_allocator_test.cc2
-rw-r--r--pw_allocator/public/pw_allocator/allocator.h105
-rw-r--r--pw_allocator/public/pw_allocator/allocator_metric_proxy.h11
-rw-r--r--pw_allocator/public/pw_allocator/allocator_testing.h11
-rw-r--r--pw_allocator/public/pw_allocator/fallback_allocator.h11
-rw-r--r--pw_allocator/public/pw_allocator/libc_allocator.h14
-rw-r--r--pw_allocator/public/pw_allocator/null_allocator.h6
-rw-r--r--pw_allocator/public/pw_allocator/simple_allocator.h10
-rw-r--r--pw_allocator/public/pw_allocator/split_free_list_allocator.h58
-rw-r--r--pw_allocator/split_free_list_allocator_test.cc17
-rw-r--r--pw_multibuf/public/pw_multibuf/internal/test_utils.h38
18 files changed, 156 insertions, 263 deletions
diff --git a/pw_allocator/allocator.cc b/pw_allocator/allocator.cc
index 15cca58bc..f63bacd69 100644
--- a/pw_allocator/allocator.cc
+++ b/pw_allocator/allocator.cc
@@ -22,23 +22,20 @@
namespace pw::allocator {
-void* Allocator::DoReallocate(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) {
+void* Allocator::DoReallocate(void* ptr, Layout layout, size_t new_size) {
if (new_size == 0) {
return nullptr;
}
- if (DoResize(ptr, old_size, old_alignment, new_size)) {
+ if (Resize(ptr, layout, new_size)) {
return ptr;
}
- void* new_ptr = DoAllocate(new_size, old_alignment);
+ void* new_ptr = DoAllocate(Layout(new_size, layout.alignment()));
if (new_ptr == nullptr) {
return nullptr;
}
- if (ptr != nullptr && old_size != 0) {
- std::memcpy(new_ptr, ptr, old_size);
- DoDeallocate(ptr, old_size, old_alignment);
+ if (ptr != nullptr && layout.size() != 0) {
+ std::memcpy(new_ptr, ptr, layout.size());
+ DoDeallocate(ptr, layout);
}
return new_ptr;
}
diff --git a/pw_allocator/allocator_metric_proxy.cc b/pw_allocator/allocator_metric_proxy.cc
index 98f3bc930..10ca68d3a 100644
--- a/pw_allocator/allocator_metric_proxy.cc
+++ b/pw_allocator/allocator_metric_proxy.cc
@@ -31,20 +31,18 @@ void AllocatorMetricProxy::Initialize(Allocator& allocator) {
memusage_.Add(count_);
}
-Status AllocatorMetricProxy::DoQuery(const void* ptr,
- size_t size,
- size_t alignment) const {
+Status AllocatorMetricProxy::DoQuery(const void* ptr, Layout layout) const {
PW_DCHECK_NOTNULL(allocator_);
- return allocator_->QueryUnchecked(ptr, size, alignment);
+ return allocator_->Query(ptr, layout);
}
-void* AllocatorMetricProxy::DoAllocate(size_t size, size_t alignment) {
+void* AllocatorMetricProxy::DoAllocate(Layout layout) {
PW_DCHECK_NOTNULL(allocator_);
- void* ptr = allocator_->AllocateUnchecked(size, alignment);
+ void* ptr = allocator_->Allocate(layout);
if (ptr == nullptr) {
return nullptr;
}
- used_.Increment(size);
+ used_.Increment(layout.size());
if (used_.value() > peak_.value()) {
peak_.Set(used_.value());
}
@@ -52,30 +50,25 @@ void* AllocatorMetricProxy::DoAllocate(size_t size, size_t alignment) {
return ptr;
}
-void AllocatorMetricProxy::DoDeallocate(void* ptr,
- size_t size,
- size_t alignment) {
+void AllocatorMetricProxy::DoDeallocate(void* ptr, Layout layout) {
PW_DCHECK_NOTNULL(allocator_);
- allocator_->DeallocateUnchecked(ptr, size, alignment);
+ allocator_->Deallocate(ptr, layout);
if (ptr == nullptr) {
return;
}
- PW_DCHECK_UINT_GE(used_.value(), size);
+ PW_DCHECK_UINT_GE(used_.value(), layout.size());
PW_DCHECK_UINT_NE(count_.value(), 0);
- used_.Set(used_.value() - size);
+ used_.Set(used_.value() - layout.size());
count_.Set(count_.value() - 1);
}
-bool AllocatorMetricProxy::DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) {
+bool AllocatorMetricProxy::DoResize(void* ptr, Layout layout, size_t new_size) {
PW_DCHECK_NOTNULL(allocator_);
- if (!allocator_->ResizeUnchecked(ptr, old_size, old_alignment, new_size)) {
+ if (!allocator_->Resize(ptr, layout, new_size)) {
return false;
}
- PW_DCHECK_UINT_GE(used_.value(), old_size);
- used_.Set(used_.value() - old_size + new_size);
+ PW_DCHECK_UINT_GE(used_.value(), layout.size());
+ used_.Set(used_.value() - layout.size() + new_size);
if (used_.value() > peak_.value()) {
peak_.Set(used_.value());
}
diff --git a/pw_allocator/allocator_test.cc b/pw_allocator/allocator_test.cc
index f0bd1981d..c41356ca8 100644
--- a/pw_allocator/allocator_test.cc
+++ b/pw_allocator/allocator_test.cc
@@ -43,11 +43,6 @@ TEST_F(AllocatorTest, ReallocateNull) {
size_t new_size = old_layout.size();
void* new_ptr = allocator.Reallocate(nullptr, old_layout, new_size);
- // Reallocate should call Resize.
- EXPECT_EQ(allocator.resize_ptr(), nullptr);
- EXPECT_EQ(allocator.resize_old_size(), old_layout.size());
- EXPECT_EQ(allocator.resize_new_size(), new_size);
-
// Resize should fail and Reallocate should call Allocate.
EXPECT_EQ(allocator.allocate_size(), new_size);
diff --git a/pw_allocator/allocator_testing.cc b/pw_allocator/allocator_testing.cc
index 47d046aae..269c47d1d 100644
--- a/pw_allocator/allocator_testing.cc
+++ b/pw_allocator/allocator_testing.cc
@@ -56,31 +56,26 @@ void AllocatorForTest::DeallocateAll() {
ResetParameters();
}
-Status AllocatorForTest::DoQuery(const void* ptr,
- size_t size,
- size_t alignment) const {
- return allocator_.QueryUnchecked(ptr, size, alignment);
+Status AllocatorForTest::DoQuery(const void* ptr, Layout layout) const {
+ return allocator_.Query(ptr, layout);
}
-void* AllocatorForTest::DoAllocate(size_t size, size_t alignment) {
- allocate_size_ = size;
- return allocator_.AllocateUnchecked(size, alignment);
+void* AllocatorForTest::DoAllocate(Layout layout) {
+ allocate_size_ = layout.size();
+ return allocator_.Allocate(layout);
}
-void AllocatorForTest::DoDeallocate(void* ptr, size_t size, size_t alignment) {
+void AllocatorForTest::DoDeallocate(void* ptr, Layout layout) {
deallocate_ptr_ = ptr;
- deallocate_size_ = size;
- return allocator_.DeallocateUnchecked(ptr, size, alignment);
+ deallocate_size_ = layout.size();
+ return allocator_.Deallocate(ptr, layout);
}
-bool AllocatorForTest::DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) {
+bool AllocatorForTest::DoResize(void* ptr, Layout layout, size_t new_size) {
resize_ptr_ = ptr;
- resize_old_size_ = old_size;
+ resize_old_size_ = layout.size();
resize_new_size_ = new_size;
- return allocator_.ResizeUnchecked(ptr, old_size, old_alignment, new_size);
+ return allocator_.Resize(ptr, layout, new_size);
}
} // namespace pw::allocator::test
diff --git a/pw_allocator/fallback_allocator.cc b/pw_allocator/fallback_allocator.cc
index cfa7bd120..1e3faf666 100644
--- a/pw_allocator/fallback_allocator.cc
+++ b/pw_allocator/fallback_allocator.cc
@@ -24,39 +24,32 @@ void FallbackAllocator::Initialize(Allocator& primary, Allocator& secondary) {
secondary_ = &secondary;
}
-Status FallbackAllocator::DoQuery(const void* ptr,
- size_t size,
- size_t alignment) const {
+Status FallbackAllocator::DoQuery(const void* ptr, Layout layout) const {
PW_DCHECK(primary_ != nullptr && secondary_ != nullptr);
- auto status = primary_->QueryUnchecked(ptr, size, alignment);
- return status.ok() ? status
- : secondary_->QueryUnchecked(ptr, size, alignment);
+ auto status = primary_->Query(ptr, layout);
+ return status.ok() ? status : secondary_->Query(ptr, layout);
}
-void* FallbackAllocator::DoAllocate(size_t size, size_t alignment) {
+void* FallbackAllocator::DoAllocate(Layout layout) {
PW_DCHECK(primary_ != nullptr && secondary_ != nullptr);
- void* ptr = primary_->AllocateUnchecked(size, alignment);
- return ptr != nullptr ? ptr : secondary_->AllocateUnchecked(size, alignment);
+ void* ptr = primary_->Allocate(layout);
+ return ptr != nullptr ? ptr : secondary_->Allocate(layout);
}
-void FallbackAllocator::DoDeallocate(void* ptr, size_t size, size_t alignment) {
+void FallbackAllocator::DoDeallocate(void* ptr, Layout layout) {
PW_DCHECK(primary_ != nullptr && secondary_ != nullptr);
- if (primary_->QueryUnchecked(ptr, size, alignment).ok()) {
- primary_->DeallocateUnchecked(ptr, size, alignment);
+ if (primary_->Query(ptr, layout).ok()) {
+ primary_->Deallocate(ptr, layout);
} else {
- secondary_->DeallocateUnchecked(ptr, size, alignment);
+ secondary_->Deallocate(ptr, layout);
}
}
-bool FallbackAllocator::DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) {
+bool FallbackAllocator::DoResize(void* ptr, Layout layout, size_t new_size) {
PW_DCHECK(primary_ != nullptr && secondary_ != nullptr);
- return primary_->QueryUnchecked(ptr, old_size, old_alignment).ok()
- ? primary_->ResizeUnchecked(ptr, old_size, old_alignment, new_size)
- : secondary_->ResizeUnchecked(
- ptr, old_size, old_alignment, new_size);
+ return primary_->Query(ptr, layout).ok()
+ ? primary_->Resize(ptr, layout, new_size)
+ : secondary_->Resize(ptr, layout, new_size);
}
} // namespace pw::allocator
diff --git a/pw_allocator/libc_allocator.cc b/pw_allocator/libc_allocator.cc
index c848d6c9f..8469bcdae 100644
--- a/pw_allocator/libc_allocator.cc
+++ b/pw_allocator/libc_allocator.cc
@@ -24,27 +24,26 @@
namespace pw::allocator {
-void* LibCAllocator::DoAllocate(size_t size, size_t alignment) {
+void* LibCAllocator::DoAllocate(Layout layout) {
// TODO: b/301930507 - `aligned_alloc` is not portable. Return null for larger
// allocations for now.
- return alignment <= alignof(std::max_align_t) ? std::malloc(size) : nullptr;
+ return layout.alignment() <= alignof(std::max_align_t)
+ ? std::malloc(layout.size())
+ : nullptr;
}
-void LibCAllocator::DoDeallocate(void* ptr, size_t, size_t) { std::free(ptr); }
+void LibCAllocator::DoDeallocate(void* ptr, Layout) { std::free(ptr); }
-bool LibCAllocator::DoResize(void*, size_t old_size, size_t, size_t new_size) {
+bool LibCAllocator::DoResize(void*, Layout layout, size_t new_size) {
// `realloc` may move memory, even when shrinking. Only return true if no
// change is needed.
- return old_size == new_size;
+ return layout.size() == new_size;
}
-void* LibCAllocator::DoReallocate(void* ptr,
- size_t,
- size_t old_alignment,
- size_t new_size) {
+void* LibCAllocator::DoReallocate(void* ptr, Layout layout, size_t new_size) {
// TODO: b/301930507 - `aligned_alloc` is not portable. Return null for larger
// allocations for now.
- return old_alignment <= alignof(std::max_align_t)
+ return layout.alignment() <= alignof(std::max_align_t)
? std::realloc(ptr, new_size)
: nullptr;
}
diff --git a/pw_allocator/libc_allocator_test.cc b/pw_allocator/libc_allocator_test.cc
index 967a1069d..15eaac212 100644
--- a/pw_allocator/libc_allocator_test.cc
+++ b/pw_allocator/libc_allocator_test.cc
@@ -43,7 +43,7 @@ TEST_F(LibCAllocatorTest, AllocateLargeAlignment) {
/// allocator has a maximum alignment of `std::align_max_t`.
size_t size = 16;
size_t alignment = alignof(std::max_align_t) * 2;
- void* ptr = allocator.AllocateUnchecked(size, alignment);
+ void* ptr = allocator.Allocate(Layout(size, alignment));
EXPECT_EQ(ptr, nullptr);
}
diff --git a/pw_allocator/null_allocator_test.cc b/pw_allocator/null_allocator_test.cc
index a257e2658..0b319646a 100644
--- a/pw_allocator/null_allocator_test.cc
+++ b/pw_allocator/null_allocator_test.cc
@@ -23,7 +23,7 @@ TEST(NullAllocatorTest, Allocate) {
// Allocate should fail, regardless of size and alignment.
for (size_t size = 1; size < 0x100; size <<= 1) {
for (size_t alignment = 1; alignment < 0x100; alignment <<= 1) {
- EXPECT_EQ(allocator.AllocateUnchecked(size, alignment), nullptr);
+ EXPECT_EQ(allocator.Allocate(Layout(size, alignment)), nullptr);
}
}
}
diff --git a/pw_allocator/public/pw_allocator/allocator.h b/pw_allocator/public/pw_allocator/allocator.h
index 0441409ca..a36d3ea3e 100644
--- a/pw_allocator/public/pw_allocator/allocator.h
+++ b/pw_allocator/public/pw_allocator/allocator.h
@@ -36,19 +36,23 @@ namespace pw::allocator {
/// @endcode
class Layout {
public:
+ constexpr Layout(size_t size, size_t alignment = alignof(std::max_align_t))
+ : size_(size), alignment_(alignment) {}
+
/// Creates a Layout for the given type.
template <typename T>
static constexpr Layout Of() {
return Layout(sizeof(T), alignof(T));
}
+ constexpr Layout Extend(size_t size) {
+ return Layout(size_ + size, alignment_);
+ }
+
size_t size() const { return size_; }
size_t alignment() const { return alignment_; }
private:
- constexpr Layout(size_t size, size_t alignment)
- : size_(size), alignment_(alignment) {}
-
size_t size_;
size_t alignment_;
};
@@ -97,15 +101,7 @@ class Allocator {
/// object.
/// @retval OK This object can re/deallocate the pointer.
Status Query(const void* ptr, Layout layout) const {
- return DoQuery(ptr, layout.size(), layout.alignment());
- }
-
- /// Like `Query`, but takes its parameters directly instead of as a `Layout`.
- ///
- /// Callers should almost always prefer `Query`. This method is meant for use
- /// by tests and other allocators implementing the virtual functions below.
- Status QueryUnchecked(const void* ptr, size_t size, size_t alignment) const {
- return DoQuery(ptr, size, alignment);
+ return DoQuery(ptr, layout);
}
/// Allocates a block of memory with the specified size and alignment.
@@ -114,9 +110,7 @@ class Allocator {
/// size of 0.
///
/// @param[in] layout Describes the memory to be allocated.
- void* Allocate(Layout layout) {
- return DoAllocate(layout.size(), layout.alignment());
- }
+ void* Allocate(Layout layout) { return DoAllocate(layout); }
template <typename T, typename... Args>
std::optional<UniquePtr<T>> MakeUnique(Args&&... args) {
@@ -130,16 +124,6 @@ class Allocator {
UniquePtr<T>::kPrivateConstructor, ptr, &kStaticLayout, this);
}
- /// Like `Allocate`, but takes its parameters directly instead of as a
- /// `Layout`.
- ///
- /// Callers should almost always prefer `Allocate`. This method is meant for
- /// use by tests and other allocators implementing the virtual functions
- /// below.
- void* AllocateUnchecked(size_t size, size_t alignment) {
- return DoAllocate(size, alignment);
- }
-
/// Releases a previously-allocated block of memory.
///
/// The given pointer must have been previously obtained from a call to either
@@ -148,17 +132,7 @@ class Allocator {
/// @param[in] ptr Pointer to previously-allocated memory.
/// @param[in] layout Describes the memory to be deallocated.
void Deallocate(void* ptr, Layout layout) {
- return DoDeallocate(ptr, layout.size(), layout.alignment());
- }
-
- /// Like `Deallocate`, but takes its parameters directly instead of as a
- /// `Layout`.
- ///
- /// Callers should almost always prefer `Deallocate`. This method is meant for
- /// use by tests and other allocators implementing the virtual functions
- /// below.
- void DeallocateUnchecked(void* ptr, size_t size, size_t alignment) {
- return DoDeallocate(ptr, size, alignment);
+ return DoDeallocate(ptr, layout);
}
/// Modifies the size of an previously-allocated block of memory without
@@ -174,19 +148,11 @@ class Allocator {
/// @param[in] ptr Pointer to previously-allocated memory.
/// @param[in] old_layout Describes the previously-allocated memory.
/// @param[in] new_size Requested new size for the memory allocation.
- bool Resize(void* ptr, Layout old_layout, size_t new_size) {
- return DoResize(ptr, old_layout.size(), old_layout.alignment(), new_size);
- }
-
- /// Like `Resize`, but takes its parameters directly instead of as a `Layout`.
- ///
- /// Callers should almost always prefer `Resize`. This method is meant for use
- /// by tests and other allocators implementing the virtual functions below.
- bool ResizeUnchecked(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) {
- return DoResize(ptr, old_size, old_alignment, new_size);
+ bool Resize(void* ptr, Layout layout, size_t new_size) {
+ if (ptr == nullptr || layout.size() == 0 || new_size == 0) {
+ return false;
+ }
+ return DoResize(ptr, layout, new_size);
}
/// Modifies the size of a previously-allocated block of memory.
@@ -206,24 +172,10 @@ class Allocator {
/// 0 will return a new allocation.
///
/// @param[in] ptr Pointer to previously-allocated memory.
- /// @param[in] old_layout Describes the previously-allocated memory.
+ /// @param[in] layout Describes the previously-allocated memory.
/// @param[in] new_size Requested new size for the memory allocation.
- void* Reallocate(void* ptr, Layout old_layout, size_t new_size) {
- return DoReallocate(
- ptr, old_layout.size(), old_layout.alignment(), new_size);
- }
-
- /// Like `Reallocate`, but takes its parameters directly instead of as a
- /// `Layout`.
- ///
- /// Callers should almost always prefer `Reallocate`. This method is meant for
- /// use by tests and other allocators implementing the virtual functions
- /// below.
- void* ReallocateUnchecked(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) {
- return DoReallocate(ptr, old_size, old_alignment, new_size);
+ void* Reallocate(void* ptr, Layout layout, size_t new_size) {
+ return DoReallocate(ptr, layout, new_size);
}
private:
@@ -233,31 +185,30 @@ class Allocator {
/// Allocators which dispatch to other allocators need to override this method
/// in order to be able to direct reallocations and deallocations to
/// appropriate allocator.
- virtual Status DoQuery(const void*, size_t, size_t) const {
+ virtual Status DoQuery(const void*, Layout) const {
return Status::Unimplemented();
}
/// Virtual `Allocate` function implemented by derived classes.
- virtual void* DoAllocate(size_t size, size_t alignment) = 0;
+ virtual void* DoAllocate(Layout layout) = 0;
/// Virtual `Deallocate` function implemented by derived classes.
- virtual void DoDeallocate(void* ptr, size_t size, size_t alignment) = 0;
+ virtual void DoDeallocate(void* ptr, Layout layout) = 0;
/// Virtual `Resize` function implemented by derived classes.
- virtual bool DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) = 0;
+ ///
+ /// The default implementation simply returns `false`, indicating that
+ /// resizing is not supported.
+ virtual bool DoResize(void* /*ptr*/, Layout /*layout*/, size_t /*new_size*/) {
+ return false;
+ }
/// Virtual `Reallocate` function that can be overridden by derived classes.
///
/// The default implementation will first try to `Resize` the data. If that is
/// unsuccessful, it will allocate an entirely new block, copy existing data,
/// and deallocate the given block.
- virtual void* DoReallocate(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size);
+ virtual void* DoReallocate(void* ptr, Layout layout, size_t new_size);
};
/// An RAII pointer to a value of type ``T`` stored within an ``Allocator``.
diff --git a/pw_allocator/public/pw_allocator/allocator_metric_proxy.h b/pw_allocator/public/pw_allocator/allocator_metric_proxy.h
index 045d89545..b4cc3a561 100644
--- a/pw_allocator/public/pw_allocator/allocator_metric_proxy.h
+++ b/pw_allocator/public/pw_allocator/allocator_metric_proxy.h
@@ -50,19 +50,16 @@ class AllocatorMetricProxy : public Allocator {
private:
/// @copydoc Allocator::Query
- Status DoQuery(const void* ptr, size_t size, size_t alignment) const override;
+ Status DoQuery(const void* ptr, Layout layout) const override;
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t size, size_t alignment) override;
+ void* DoAllocate(Layout layout) override;
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override;
+ void DoDeallocate(void* ptr, Layout layout) override;
/// @copydoc Allocator::Resize
- bool DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) override;
+ bool DoResize(void* ptr, Layout layout, size_t new_size) override;
metric::Group memusage_;
Allocator* allocator_ = nullptr;
diff --git a/pw_allocator/public/pw_allocator/allocator_testing.h b/pw_allocator/public/pw_allocator/allocator_testing.h
index 41077522d..f5c84c9ee 100644
--- a/pw_allocator/public/pw_allocator/allocator_testing.h
+++ b/pw_allocator/public/pw_allocator/allocator_testing.h
@@ -56,19 +56,16 @@ class AllocatorForTest : public Allocator {
using BlockType = Block<>;
/// @copydoc Allocator::Query
- Status DoQuery(const void* ptr, size_t size, size_t alignment) const override;
+ Status DoQuery(const void* ptr, Layout layout) const override;
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t size, size_t alignment) override;
+ void* DoAllocate(Layout layout) override;
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override;
+ void DoDeallocate(void* ptr, Layout layout) override;
/// @copydoc Allocator::Resize
- bool DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) override;
+ bool DoResize(void* ptr, Layout layout, size_t new_size) override;
SimpleAllocator allocator_;
size_t allocate_size_ = 0;
diff --git a/pw_allocator/public/pw_allocator/fallback_allocator.h b/pw_allocator/public/pw_allocator/fallback_allocator.h
index 61c20fd2b..5707c1aee 100644
--- a/pw_allocator/public/pw_allocator/fallback_allocator.h
+++ b/pw_allocator/public/pw_allocator/fallback_allocator.h
@@ -33,19 +33,16 @@ class FallbackAllocator : public Allocator {
private:
/// @copydoc Allocator::Query
- Status DoQuery(const void* ptr, size_t size, size_t alignment) const override;
+ Status DoQuery(const void* ptr, Layout layout) const override;
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t size, size_t alignment) override;
+ void* DoAllocate(Layout layout) override;
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override;
+ void DoDeallocate(void* ptr, Layout layout) override;
/// @copydoc Allocator::Resize
- bool DoResize(void* ptr,
- size_t old_size,
- size_t alignment,
- size_t new_size) override;
+ bool DoResize(void* ptr, Layout layout, size_t new_size) override;
Allocator* primary_ = nullptr;
Allocator* secondary_ = nullptr;
diff --git a/pw_allocator/public/pw_allocator/libc_allocator.h b/pw_allocator/public/pw_allocator/libc_allocator.h
index 9f2fcd6da..70f67f286 100644
--- a/pw_allocator/public/pw_allocator/libc_allocator.h
+++ b/pw_allocator/public/pw_allocator/libc_allocator.h
@@ -27,22 +27,16 @@ class LibCAllocator : public Allocator {
private:
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t size, size_t alignment) override;
+ void* DoAllocate(Layout layout) override;
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override;
+ void DoDeallocate(void* ptr, Layout layout) override;
/// @copydoc Allocator::Resize
- bool DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) override;
+ bool DoResize(void* ptr, Layout layout, size_t new_size) override;
/// @copydoc Allocator::Reallocate
- void* DoReallocate(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) override;
+ void* DoReallocate(void* ptr, Layout layout, size_t new_size) override;
};
} // namespace pw::allocator
diff --git a/pw_allocator/public/pw_allocator/null_allocator.h b/pw_allocator/public/pw_allocator/null_allocator.h
index 55a7f62f4..b4c3ba6aa 100644
--- a/pw_allocator/public/pw_allocator/null_allocator.h
+++ b/pw_allocator/public/pw_allocator/null_allocator.h
@@ -29,13 +29,13 @@ class NullAllocator : public Allocator {
private:
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t, size_t) override { return nullptr; }
+ void* DoAllocate(Layout) override { return nullptr; }
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void*, size_t, size_t) override {}
+ void DoDeallocate(void*, Layout) override {}
/// @copydoc Allocator::Resize
- bool DoResize(void*, size_t, size_t, size_t) override { return false; }
+ bool DoResize(void*, Layout, size_t) override { return false; }
};
} // namespace pw::allocator
diff --git a/pw_allocator/public/pw_allocator/simple_allocator.h b/pw_allocator/public/pw_allocator/simple_allocator.h
index 98513426e..73662d452 100644
--- a/pw_allocator/public/pw_allocator/simple_allocator.h
+++ b/pw_allocator/public/pw_allocator/simple_allocator.h
@@ -41,7 +41,7 @@ class SimpleAllocator : public Allocator {
private:
/// @copydoc Allocator::Query
- Status DoQuery(const void* ptr, size_t, size_t) const override {
+ Status DoQuery(const void* ptr, Layout) const override {
for (auto* block : Range(blocks_)) {
if (block->UsableSpace() == ptr) {
return OkStatus();
@@ -51,9 +51,9 @@ class SimpleAllocator : public Allocator {
}
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t size, size_t alignment) override {
+ void* DoAllocate(Layout layout) override {
for (auto* block : Range(blocks_)) {
- if (Block::AllocFirst(block, size, alignment).ok()) {
+ if (Block::AllocFirst(block, layout.size(), layout.alignment()).ok()) {
return block->UsableSpace();
}
}
@@ -61,7 +61,7 @@ class SimpleAllocator : public Allocator {
}
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void* ptr, size_t, size_t) override {
+ void DoDeallocate(void* ptr, Layout) override {
if (ptr == nullptr) {
return;
}
@@ -71,7 +71,7 @@ class SimpleAllocator : public Allocator {
}
/// @copydoc Allocator::Resize
- bool DoResize(void* ptr, size_t, size_t, size_t new_size) override {
+ bool DoResize(void* ptr, Layout, size_t new_size) override {
if (ptr == nullptr) {
return false;
}
diff --git a/pw_allocator/public/pw_allocator/split_free_list_allocator.h b/pw_allocator/public/pw_allocator/split_free_list_allocator.h
index 4ad221ae3..46fd9d971 100644
--- a/pw_allocator/public/pw_allocator/split_free_list_allocator.h
+++ b/pw_allocator/public/pw_allocator/split_free_list_allocator.h
@@ -90,10 +90,10 @@ class SplitFreeListAllocator : public BaseSplitFreeListAllocator {
using ReverseRange = typename BlockType::ReverseRange;
/// @copydoc Allocator::Dispatch
- Status DoQuery(const void* ptr, size_t size, size_t alignment) const override;
+ Status DoQuery(const void* ptr, Layout layout) const override;
/// @copydoc Allocator::Allocate
- void* DoAllocate(size_t size, size_t alignment) override;
+ void* DoAllocate(Layout layout) override;
/// Allocate a large chunk of memory.
///
@@ -101,9 +101,8 @@ class SplitFreeListAllocator : public BaseSplitFreeListAllocator {
/// addresses. If a block needs to be fragmented, the returned pointer will be
/// from the lower-addressed part of the block.
///
- /// @param[in] size Length of requested memory.
- /// @param[in] alignment Boundary to align the returned memory to.
- void* DoAllocateLarge(size_t size, size_t alignment);
+ /// @param[in] layout Describes the memory to be allocated.
+ void* DoAllocateLarge(Layout layout);
/// Allocate a small chunk of memory.
///
@@ -111,18 +110,14 @@ class SplitFreeListAllocator : public BaseSplitFreeListAllocator {
/// addresses. If a block needs to be fragmented, the returned pointer will be
/// from the higher-addressed part of the block.
///
- /// @param[in] size Length of requested memory.
- /// @param[in] alignment Boundary to align the returned memory to.
- void* DoAllocateSmall(size_t size, size_t alignment);
+ /// @param[in] layout Describes the memory to be allocated.
+ void* DoAllocateSmall(Layout layout);
/// @copydoc Allocator::Deallocate
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override;
+ void DoDeallocate(void* ptr, Layout layout) override;
/// @copydoc Allocator::Resize
- bool DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
- size_t new_size) override;
+ bool DoResize(void* ptr, Layout layout, size_t new_size) override;
// Represents the entire memory region for this allocator.
void* begin_ = nullptr;
@@ -189,34 +184,30 @@ Status SplitFreeListAllocator<BlockType>::Init(ByteSpan region,
template <typename BlockType>
Status SplitFreeListAllocator<BlockType>::DoQuery(const void* ptr,
- size_t,
- size_t) const {
+ Layout) const {
return (ptr < begin_ || end_ <= ptr) ? Status::OutOfRange() : OkStatus();
}
template <typename BlockType>
-void* SplitFreeListAllocator<BlockType>::DoAllocate(size_t size,
- size_t alignment) {
- if (begin_ == nullptr || size == 0) {
+void* SplitFreeListAllocator<BlockType>::DoAllocate(Layout layout) {
+ if (begin_ == nullptr || layout.size() == 0) {
return nullptr;
}
- void* ptr = size < threshold_ ? DoAllocateSmall(size, alignment)
- : DoAllocateLarge(size, alignment);
-
- // Update the first and last free blocks.
- return ptr;
+ size_t size = layout.size();
+ size_t alignment = std::max(layout.alignment(), BlockType::kAlignment);
+ layout = Layout(size, alignment);
+ return size < threshold_ ? DoAllocateSmall(layout) : DoAllocateLarge(layout);
}
template <typename BlockType>
-void* SplitFreeListAllocator<BlockType>::DoAllocateSmall(size_t size,
- size_t alignment) {
+void* SplitFreeListAllocator<BlockType>::DoAllocateSmall(Layout layout) {
// Update the cached last free block.
while (last_free_->Used() && first_free_ != last_free_) {
last_free_ = last_free_->Prev();
}
// Search backwards for the first block that can hold this allocation.
for (auto* block : ReverseRange(last_free_, first_free_)) {
- if (BlockType::AllocLast(block, size, alignment).ok()) {
+ if (BlockType::AllocLast(block, layout.size(), layout.alignment()).ok()) {
return block->UsableSpace();
}
}
@@ -225,15 +216,14 @@ void* SplitFreeListAllocator<BlockType>::DoAllocateSmall(size_t size,
}
template <typename BlockType>
-void* SplitFreeListAllocator<BlockType>::DoAllocateLarge(size_t size,
- size_t alignment) {
+void* SplitFreeListAllocator<BlockType>::DoAllocateLarge(Layout layout) {
// Update the cached first free block.
while (first_free_->Used() && first_free_ != last_free_) {
first_free_ = first_free_->Next();
}
// Search forwards for the first block that can hold this allocation.
for (auto* block : Range(first_free_, last_free_)) {
- if (BlockType::AllocFirst(block, size, alignment).ok()) {
+ if (BlockType::AllocFirst(block, layout.size(), layout.alignment()).ok()) {
// A new last free block may be split off the end of the allocated block.
if (last_free_ <= block) {
last_free_ = block->Last() ? block : block->Next();
@@ -246,9 +236,7 @@ void* SplitFreeListAllocator<BlockType>::DoAllocateLarge(size_t size,
}
template <typename BlockType>
-void SplitFreeListAllocator<BlockType>::DoDeallocate(void* ptr,
- size_t,
- size_t) {
+void SplitFreeListAllocator<BlockType>::DoDeallocate(void* ptr, Layout) {
// Do nothing if uninitialized or no memory block pointer.
if (begin_ == nullptr || ptr < begin_ || end_ <= ptr) {
return;
@@ -270,12 +258,10 @@ void SplitFreeListAllocator<BlockType>::DoDeallocate(void* ptr,
template <typename BlockType>
bool SplitFreeListAllocator<BlockType>::DoResize(void* ptr,
- size_t old_size,
- size_t old_alignment,
+ Layout layout,
size_t new_size) {
// Fail to resize is uninitialized or invalid parameters.
- if (begin_ == nullptr || ptr == nullptr || old_size == 0 || new_size == 0 ||
- !DoQuery(ptr, old_size, old_alignment).ok()) {
+ if (begin_ == nullptr || !DoQuery(ptr, layout).ok()) {
return false;
}
diff --git a/pw_allocator/split_free_list_allocator_test.cc b/pw_allocator/split_free_list_allocator_test.cc
index ab4bab42b..c519849d6 100644
--- a/pw_allocator/split_free_list_allocator_test.cc
+++ b/pw_allocator/split_free_list_allocator_test.cc
@@ -118,15 +118,15 @@ TEST_F(SplitFreeListAllocatorTest, AllocateTooLarge) {
TEST_F(SplitFreeListAllocatorTest, AllocateLargeAlignment) {
constexpr size_t kSize = sizeof(uint32_t);
constexpr size_t kAlignment = 64;
- ptrs_[0] = allocator_->AllocateUnchecked(kSize, kAlignment);
+ ptrs_[0] = allocator_->Allocate(Layout(kSize, kAlignment));
ASSERT_NE(ptrs_[0], nullptr);
EXPECT_EQ(reinterpret_cast<uintptr_t>(ptrs_[0]) % kAlignment, 0U);
UseMemory(ptrs_[0], kSize);
- ptrs_[1] = allocator_->AllocateUnchecked(kSize, kAlignment);
+ ptrs_[1] = allocator_->Allocate(Layout(kSize, kAlignment));
ASSERT_NE(ptrs_[1], nullptr);
EXPECT_EQ(reinterpret_cast<uintptr_t>(ptrs_[1]) % kAlignment, 0U);
- UseMemory(ptrs_[0], kSize);
+ UseMemory(ptrs_[1], kSize);
}
TEST_F(SplitFreeListAllocatorTest, AllocateFromUnaligned) {
@@ -165,26 +165,27 @@ TEST_F(SplitFreeListAllocatorTest, AllocateAlignmentFailure) {
outer_size - (BlockType::kBlockOverhead * 3 + inner_size1 + inner_size2);
// Allocate all the blocks.
- ptrs_[0] = allocator_->AllocateUnchecked(inner_size1, 1);
+ ptrs_[0] = allocator_->Allocate(Layout(inner_size1, 1));
ASSERT_NE(ptrs_[0], nullptr);
- ptrs_[1] = allocator_->AllocateUnchecked(inner_size2, 1);
+ ptrs_[1] = allocator_->Allocate(Layout(inner_size2, 1));
ASSERT_NE(ptrs_[1], nullptr);
- ptrs_[2] = allocator_->AllocateUnchecked(inner_size3, 1);
+ ptrs_[2] = allocator_->Allocate(Layout(inner_size3, 1));
ASSERT_NE(ptrs_[2], nullptr);
// If done correctly, the second block's usable space should be unaligned.
EXPECT_NE(reinterpret_cast<uintptr_t>(ptrs_[1]) % kAlignment, 0U);
// Free the second region. This leaves an unaligned region available.
- allocator_->DeallocateUnchecked(ptrs_[1], inner_size2, 1);
+ allocator_->Deallocate(ptrs_[1], Layout(inner_size2, 1));
ptrs_[1] = nullptr;
// The allocator should be unable to create an aligned region..
- ptrs_[3] = allocator_->AllocateUnchecked(inner_size2, kAlignment);
+ ptrs_[3] = allocator_->Allocate(Layout(inner_size2, kAlignment));
EXPECT_EQ(ptrs_[3], nullptr);
}
+
TEST_F(SplitFreeListAllocatorTest, DeallocateNull) {
constexpr Layout layout = Layout::Of<uint8_t>();
allocator_->Deallocate(nullptr, layout);
diff --git a/pw_multibuf/public/pw_multibuf/internal/test_utils.h b/pw_multibuf/public/pw_multibuf/internal/test_utils.h
index 3e713fff8..07e325016 100644
--- a/pw_multibuf/public/pw_multibuf/internal/test_utils.h
+++ b/pw_multibuf/public/pw_multibuf/internal/test_utils.h
@@ -41,17 +41,16 @@ class TrackingAllocator : public pw::allocator::Allocator {
size_t used() const { return alloc_stats_.used(); }
protected:
- void* DoAllocate(size_t size, size_t alignment) override {
- return alloc_stats_.AllocateUnchecked(size, alignment);
+ void* DoAllocate(allocator::Layout layout) override {
+ return alloc_stats_.Allocate(layout);
}
bool DoResize(void* ptr,
- size_t old_size,
- size_t old_align,
+ allocator::Layout old_layout,
size_t new_size) override {
- return alloc_stats_.ResizeUnchecked(ptr, old_size, old_align, new_size);
+ return alloc_stats_.Resize(ptr, old_layout, new_size);
}
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override {
- alloc_stats_.DeallocateUnchecked(ptr, size, alignment);
+ void DoDeallocate(void* ptr, allocator::Layout layout) override {
+ alloc_stats_.Deallocate(ptr, layout);
}
private:
@@ -70,17 +69,16 @@ class TrackingAllocatorWithMemory : public pw::allocator::Allocator {
TrackingAllocatorWithMemory() : mem_(), alloc_(mem_) {}
size_t count() const { return alloc_.count(); }
size_t used() const { return alloc_.used(); }
- void* DoAllocate(size_t size, size_t alignment) override {
- return alloc_.AllocateUnchecked(size, alignment);
+ void* DoAllocate(allocator::Layout layout) override {
+ return alloc_.Allocate(layout);
}
bool DoResize(void* ptr,
- size_t old_size,
- size_t old_align,
+ allocator::Layout old_layout,
size_t new_size) override {
- return alloc_.ResizeUnchecked(ptr, old_size, old_align, new_size);
+ return alloc_.Resize(ptr, old_layout, new_size);
}
- void DoDeallocate(void* ptr, size_t size, size_t alignment) override {
- alloc_.DeallocateUnchecked(ptr, size, alignment);
+ void DoDeallocate(void* ptr, allocator::Layout layout) override {
+ alloc_.Deallocate(ptr, layout);
}
private:
@@ -121,9 +119,9 @@ class HeaderChunkRegionTracker final : public ChunkRegionTracker {
/// or ``nullptr`` if the allocation failed.
static HeaderChunkRegionTracker* AllocateRegion(
pw::allocator::Allocator* alloc, size_t size) {
- const size_t alloc_size = size + sizeof(HeaderChunkRegionTracker);
- const size_t align = alignof(HeaderChunkRegionTracker);
- void* ptr = alloc->AllocateUnchecked(alloc_size, align);
+ auto layout =
+ allocator::Layout::Of<HeaderChunkRegionTracker>().Extend(size);
+ void* ptr = alloc->Allocate(layout);
if (ptr == nullptr) {
return nullptr;
}
@@ -138,11 +136,11 @@ class HeaderChunkRegionTracker final : public ChunkRegionTracker {
protected:
void Destroy() final {
std::byte* ptr = reinterpret_cast<std::byte*>(this);
- const size_t size = sizeof(HeaderChunkRegionTracker) + region_.size();
- const size_t align = alignof(HeaderChunkRegionTracker);
+ auto layout = allocator::Layout::Of<HeaderChunkRegionTracker>().Extend(
+ region_.size());
auto alloc = alloc_;
std::destroy_at(this);
- alloc->DeallocateUnchecked(ptr, size, align);
+ alloc->Deallocate(ptr, layout);
}
void* AllocateChunkClass() final {
return alloc_->Allocate(pw::allocator::Layout::Of<Chunk>());