Skip to content

Commit

Permalink
pw_allocator: Add NullAllocator
Browse files Browse the repository at this point in the history
This CL adds NullAllocator, a memory allocator which always fails. This
can be used as part of a larger memory framework to disallow memory
allocations under specific circumstances.

Change-Id: I2b005660f611afc975f98097b88f1fe0c4b1af27
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/172233
Reviewed-by: Taylor Cramer <[email protected]>
Commit-Queue: Aaron Green <[email protected]>
  • Loading branch information
nopsledder authored and CQ Bot Account committed Sep 25, 2023
1 parent b9656ec commit 5715233
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
22 changes: 22 additions & 0 deletions pw_allocator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ pw_cc_library(
],
)

pw_cc_library(
name = "null_allocator",
hdrs = [
"public/pw_allocator/null_allocator.h",
],
includes = ["public"],
deps = [
":allocator",
],
)

pw_cc_library(
name = "allocator_testing",
srcs = [
Expand Down Expand Up @@ -196,6 +207,17 @@ pw_cc_test(
],
)

pw_cc_test(
name = "null_allocator_test",
srcs = [
"null_allocator_test.cc",
],
deps = [
":null_allocator",
"//pw_unit_test",
],
)

pw_cc_test(
name = "split_free_list_allocator_test",
srcs = [
Expand Down
12 changes: 12 additions & 0 deletions pw_allocator/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ pw_source_set("freelist_heap") {
sources = [ "freelist_heap.cc" ]
}

pw_source_set("null_allocator") {
public_configs = [ ":default_config" ]
public = [ "public/pw_allocator/null_allocator.h" ]
public_deps = [ ":allocator" ]
}

pw_source_set("split_free_list_allocator") {
public_configs = [ ":default_config" ]
public = [ "public/pw_allocator/split_free_list_allocator.h" ]
Expand All @@ -124,6 +130,7 @@ pw_test_group("tests") {
":fallback_allocator_test",
":freelist_test",
":freelist_heap_test",
":null_allocator_test",
":split_free_list_allocator_test",
]
}
Expand Down Expand Up @@ -182,6 +189,11 @@ pw_test("freelist_heap_test") {
sources = [ "freelist_heap_test.cc" ]
}

pw_test("null_allocator_test") {
deps = [ ":null_allocator" ]
sources = [ "null_allocator_test.cc" ]
}

pw_test("split_free_list_allocator_test") {
deps = [
":split_free_list_allocator",
Expand Down
20 changes: 20 additions & 0 deletions pw_allocator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ pw_add_library(pw_allocator.split_free_list_allocator STATIC
pw_bytes
)

pw_add_library(pw_allocator.null_allocator INTERFACE
HEADERS
public/pw_allocator/null_allocator.h
PUBLIC_INCLUDES
public
PUBLIC_DEPS
pw_allocator.allocator
)

pw_add_library(pw_allocator.allocator_testing STATIC
HEADERS
pw_allocator_private/allocator_testing.h
Expand Down Expand Up @@ -166,6 +175,17 @@ pw_add_test(pw_allocator.freelist_heap_test
pw_allocator
)

pw_add_test(pw_allocator.null_allocator_test
SOURCES
null_allocator_test.cc
PRIVATE_DEPS
pw_allocator.null_allocator
pw_unit_test
GROUPS
modules
pw_allocator
)

pw_add_test(pw_allocator.split_free_list_allocator_test
SOURCES
split_free_list_allocator_test.cc
Expand Down
2 changes: 2 additions & 0 deletions pw_allocator/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Provided implementations of the ``Allocator`` interface include:

- ``FallbackAllocator``: Dispatches first to a primary allocator, and, if that
fails, to a secondary alloator.
- ``NullAllocator``: Always fails. This may be useful if allocations should be
disallowed under specific circumstances.
- ``SplitFreeListAllocator``: Tracks free blocks using a free list, and splits
large and small allocations between the front and back, respectively, of its
memory region in order to reduce fragmentation.
Expand Down
38 changes: 38 additions & 0 deletions pw_allocator/null_allocator_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_allocator/null_allocator.h"

#include "gtest/gtest.h"

namespace pw::allocator {

TEST(NullAllocatorTest, Allocate) {
NullAllocator allocator;
// 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);
}
}
}

TEST(NullAllocatorTest, Resize) {
NullAllocator allocator;
// It is not possible to get a valid pointer from Allocate.
constexpr Layout layout = Layout::Of<uint8_t>();
EXPECT_FALSE(allocator.Resize(this, layout, 1));
}

} // namespace pw::allocator
41 changes: 41 additions & 0 deletions pw_allocator/public/pw_allocator/null_allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once

#include "pw_allocator/allocator.h"

namespace pw::allocator {

/// A memory allocator that always fails to allocate memory.
///
/// A null allocator may be useful as part of a larger framework if allocation
/// should be disallowed under certain circumstances. For example, a function
/// that returns different allocators based on an input parameter may return a
/// null allocator when given an invalid or unsupported parameter value.
class NullAllocator : public Allocator {
public:
constexpr NullAllocator() = default;

private:
/// @copydoc Allocator::Allocate
void* DoAllocate(size_t, size_t) override { return nullptr; }

/// @copydoc Allocator::Deallocate
void DoDeallocate(void*, size_t, size_t) override {}

/// @copydoc Allocator::Resize
bool DoResize(void*, size_t, size_t, size_t) override { return false; }
};

} // namespace pw::allocator

0 comments on commit 5715233

Please sign in to comment.