Skip to content

Commit

Permalink
PMR support for cetl::unbounded_variant & cetl::pmr::function. (#124
Browse files Browse the repository at this point in the history
)

- Added `IsPmr` support to `cetl::unbounded_variant`.
- Added new `cetl::pmr::function` (aka `std::function` but with PMR
instead of c++ heap).
- Added new `cetl::pmr::InterfacePtr` and its
`InterfaceFactrory::make_unique`
- based on `std::unique_ptr` but with custom PMR-based allocator and
deleter
- allows to hide implementation (aka Concrete) type from result
InterfacePtr
  - allows to delete destructor from an interface type
  • Loading branch information
serges147 authored Jun 3, 2024
1 parent 63a1184 commit 6510714
Show file tree
Hide file tree
Showing 17 changed files with 3,274 additions and 333 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/cetlvast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:

- name: Cache ext modules
id: cetlvast-ext
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: cetlvast-ext-cache
with:
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
- uses: actions/checkout@v4
- name: Cache ext modules
id: cetlvast-ext
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: cetlvast-ext-cache
with:
Expand Down Expand Up @@ -136,7 +136,7 @@ jobs:

- name: Cache ext modules
id: cetlvast-ext
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: cetlvast-ext-cache
with:
Expand Down
1 change: 1 addition & 0 deletions cetlvast/cmake/compiler_flag_sets/default.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "Release build. Setting optimization flags.")
list(APPEND C_FLAG_SET
"-O1"
"-fno-delete-null-pointer-checks" # https://github.com/OpenCyphal-Garage/libcyphal/pull/347#discussion_r1572254288
)
else()

Expand Down
66 changes: 66 additions & 0 deletions cetlvast/include/cetlvast/memory_resource_mock.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/// @copyright
/// Copyright (C) OpenCyphal Development Team <opencyphal.org>
/// Copyright Amazon.com Inc. or its affiliates.
/// SPDX-License-Identifier: MIT

#ifndef CETLVAST_MEMORY_RESOURCE_MOCK_HPP_INCLUDED
#define CETLVAST_MEMORY_RESOURCE_MOCK_HPP_INCLUDED

#include "cetl/pf17/cetlpf.hpp"
#include "cetl/pmr/memory.hpp"

#include <gmock/gmock.h>

namespace cetlvast
{

class MemoryResourceMock : public cetl::pmr::memory_resource
{
public:
cetl::pmr::memory_resource* resource() noexcept
{
return this;
}

MOCK_METHOD(void*, do_allocate, (std::size_t, std::size_t), (override));
MOCK_METHOD(void, do_deallocate, (void*, std::size_t, std::size_t));
// NOLINTNEXTLINE(bugprone-exception-escape)
MOCK_METHOD(bool, do_is_equal, (const memory_resource&), (const, noexcept, override));

#if (__cplusplus < CETL_CPP_STANDARD_17)
// NOLINTNEXTLINE(bugprone-exception-escape)
MOCK_METHOD(std::size_t, do_max_size, (), (const, noexcept, override));
MOCK_METHOD(void*, do_reallocate, (void*, std::size_t, std::size_t, std::size_t), (override));
#endif

void redirectExpectedCallsTo(cetl::pmr::memory_resource& mr)
{
using ::testing::_;

EXPECT_CALL(*this, do_allocate(_, _))
.WillRepeatedly([&mr](std::size_t size_bytes, std::size_t alignment) -> void* {
return mr.allocate(size_bytes, alignment);
});
EXPECT_CALL(*this, do_deallocate(_, _, _))
.WillRepeatedly([&mr](void* p, std::size_t size_bytes, std::size_t alignment) {
mr.deallocate(p, size_bytes, alignment);
});
EXPECT_CALL(*this, do_is_equal(_)).WillRepeatedly([&mr](const memory_resource& rhs) {
return mr.is_equal(rhs);
});

#if (__cplusplus < CETL_CPP_STANDARD_17)
EXPECT_CALL(*this, do_max_size()).WillRepeatedly([&mr]() { return mr.max_size(); });
EXPECT_CALL(*this, do_reallocate(_, _, _, _))
.WillRepeatedly(
[&mr](void* ptr, std::size_t old_size_bytes, std::size_t new_size_bytes, std::size_t alignment) {
return mr.reallocate(ptr, old_size_bytes, new_size_bytes, alignment);
});
#endif
}

}; // MemoryResourceMock

} // namespace cetlvast

#endif // CETLVAST_MEMORY_RESOURCE_MOCK_HPP_INCLUDED
94 changes: 94 additions & 0 deletions cetlvast/include/cetlvast/tracking_memory_resource.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/// @copyright
/// Copyright (C) OpenCyphal Development Team <opencyphal.org>
/// Copyright Amazon.com Inc. or its affiliates.
/// SPDX-License-Identifier: MIT

#ifndef CETLVAST_TRACKING_MEMORY_RESOURCE_HPP_INCLUDED
#define CETLVAST_TRACKING_MEMORY_RESOURCE_HPP_INCLUDED

#include "cetl/pf17/cetlpf.hpp"
#include "cetl/pmr/memory.hpp"

#include <ostream>
#include <vector>

namespace cetlvast
{

class TrackingMemoryResource final : public cetl::pmr::memory_resource
{
public:
struct Allocation final
{
std::size_t size;
void* pointer;

friend void PrintTo(const Allocation& alloc, std::ostream* os)
{
*os << "\n{ptr=0x" << std::hex << alloc.pointer << ", size=" << std::dec << alloc.size << "}";
}
};

// NOLINTBEGIN
std::vector<Allocation> allocations{};
std::size_t total_allocated_bytes = 0;
std::size_t total_deallocated_bytes = 0;
// NOLINTEND

private:
// MARK: cetl::pmr::memory_resource

void* do_allocate(std::size_t size_bytes, std::size_t alignment) override
{
if (alignment > alignof(std::max_align_t))
{
#if defined(__cpp_exceptions)
throw std::bad_alloc();
#endif
return nullptr;
}

auto ptr = std::malloc(size_bytes);

total_allocated_bytes += size_bytes;
allocations.push_back({size_bytes, ptr});

return ptr;
}

void do_deallocate(void* ptr, std::size_t size_bytes, std::size_t) override
{
auto prev_alloc = std::find_if(allocations.cbegin(), allocations.cend(), [ptr](const auto& alloc) {
return alloc.pointer == ptr;
});
if (prev_alloc != allocations.cend())
{
allocations.erase(prev_alloc);
}
total_deallocated_bytes += size_bytes;

std::free(ptr);
}

#if (__cplusplus < CETL_CPP_STANDARD_17)

void* do_reallocate(void* ptr, std::size_t old_size_bytes, std::size_t new_size_bytes, std::size_t) override
{
total_allocated_bytes -= old_size_bytes;
total_allocated_bytes += new_size_bytes;

return std::realloc(ptr, new_size_bytes);
}

#endif

bool do_is_equal(const memory_resource& rhs) const noexcept override
{
return (&rhs == this);
}

}; // TrackingMemoryResource

} // namespace cetlvast

#endif // CETLVAST_TRACKING_MEMORY_RESOURCE_HPP_INCLUDED
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ int main()

#ifndef CETLVAST_COMPILETEST_PRECHECK

// Verify at `cetl::detail::base_storage::get_ptr const`
// Verify at `cetl::detail::base_storage::check_footprint` (called from `base_access::get_ptr() const`).
// ```
// static_assert(sizeof(ValueType) <= Footprint,
// "Cannot contain the requested type since the footprint is too small");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ int main()

#ifndef CETLVAST_COMPILETEST_PRECHECK

// Verify at `cetl::detail::base_storage::get_ptr`
// Verify at `cetl::detail::base_storage::check_footprint` (called from `base_access::get_ptr()`).
// ```
// static_assert(sizeof(ValueType) <= Footprint,
// "Cannot contain the requested type since the footprint is too small");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ int main()

#ifndef CETLVAST_COMPILETEST_PRECHECK

// Verify at `cetl::detail::base_storage::make_handlers`
// Verify at `cetl::detail::base_storage::check_footprint` (called from `base_access::make_handlers()`).
// ```
// static_assert(sizeof(Tp) <= Footprint, "Enlarge the footprint");
// ```
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// @file
/// Compile test that ensures it's impossible to use non-PMR `unbounded_variant` with zero footprint.
///
/// @copyright
/// Copyright (C) OpenCyphal Development Team <opencyphal.org>
/// Copyright Amazon.com Inc. or its affiliates.
/// SPDX-License-Identifier: MIT
///

#include "cetl/unbounded_variant.hpp"

#include <cstdint>

int main()
{
#ifndef CETLVAST_COMPILETEST_PRECHECK

cetl::unbounded_variant<0> test{};

#else

cetl::unbounded_variant<1> test{};

#endif

return 0;
}
Loading

0 comments on commit 6510714

Please sign in to comment.