Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iox #842 cleanup memory provider and memory block #843

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -45,27 +46,27 @@ class MemPoolCollectionMemoryBlock final : public MemoryBlock
MemPoolCollectionMemoryBlock& operator=(const MemPoolCollectionMemoryBlock&) = delete;
MemPoolCollectionMemoryBlock& operator=(MemPoolCollectionMemoryBlock&&) = delete;

/// @brief Implementation of MemoryBlock::size
/// @return the size of type T
/// @copydoc MemoryBlock::size
/// @note The size for all the MemPools
uint64_t size() const noexcept override;

/// @brief Implementation of MemoryBlock::alignment
/// @return the alignment of type T
/// @copydoc MemoryBlock::alignment
/// @note The memory alignment for the MemPools
uint64_t alignment() const noexcept override;

/// @brief Implementation of MemoryBlock::memoryAvailable
/// This will create the MemPools
/// @param [in] memory pointer to a valid memory location to place the mempools
void memoryAvailable(void* memory) noexcept override;

/// @brief Implementation of MemoryBlock::destroy
/// This will clean up the MemPools
void destroy() noexcept override;

/// @brief This function enables the access to the MemoryManager for the MemPools
/// @return an optional pointer to the underlying type, cxx::nullopt_t if value is not initialized
cxx::optional<mepoo::MemoryManager*> memoryManager() const noexcept;

protected:
/// @copydoc MemoryBlock::memoryAvailable
/// @note This will create the MemPools at the location `memory` points to
void onMemoryAvailable(cxx::not_null<void*> memory) noexcept override;

/// @copydoc MemoryBlock::destroy
/// @note This will clean up the MemPools
void destroy() noexcept override;

private:
mepoo::MePooConfig m_memPoolConfig;
mepoo::MemoryManager* m_memoryManager{nullptr};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -40,27 +41,27 @@ class MemPoolSegmentManagerMemoryBlock : public MemoryBlock
MemPoolSegmentManagerMemoryBlock& operator=(const MemPoolSegmentManagerMemoryBlock&) = delete;
MemPoolSegmentManagerMemoryBlock& operator=(MemPoolSegmentManagerMemoryBlock&&) = delete;

/// @brief Implementation of MemoryBlock::size
/// @return the size of for SegmentManager
/// @copydoc MemoryBlock::size
/// @note the size of for SegmentManager
uint64_t size() const noexcept override;

/// @brief Implementation of MemoryBlock::alignment
/// @return the memory alignment for SegmentManager
/// @copydoc MemoryBlock::alignment
/// @note The memory alignment for SegmentManager
uint64_t alignment() const noexcept override;

/// @brief Implementation of MemoryBlock::memoryAvailable
/// This will create the SegmentManager
/// @param [in] memory pointer to a valid memory location to place the mempools
void memoryAvailable(void* memory) noexcept override;

/// @brief Implementation of MemoryBlock::destroy
/// This will clean up the SegmentManager
void destroy() noexcept override;

/// @brief This function enables the access to the SegmentManager
/// @return an optional pointer to the underlying type, cxx::nullopt_t if value is not initialized
cxx::optional<mepoo::SegmentManager<>*> segmentManager() const noexcept;

protected:
/// @copydoc MemoryBlock::memoryAvailable
/// @note This will create the SegmentManager at the location `memory` points to
void onMemoryAvailable(cxx::not_null<void*> memory) noexcept override;

/// @copydoc MemoryBlock::destroy
/// @note This will clean up the SegmentManager
void destroy() noexcept override;

private:
mepoo::SegmentManager<>* m_segmentManager{nullptr};
mepoo::SegmentConfig m_segmentConfig;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -40,27 +41,27 @@ class PortPoolMemoryBlock : public MemoryBlock
PortPoolMemoryBlock& operator=(const PortPoolMemoryBlock&) = delete;
PortPoolMemoryBlock& operator=(PortPoolMemoryBlock&&) = delete;

/// @brief Implementation of MemoryBlock::size
/// @return the size of for all the ports
/// @copydoc MemoryBlock::size
/// @note The size of for all the ports
uint64_t size() const noexcept override;

/// @brief Implementation of MemoryBlock::alignment
/// @return the memory alignment for the ports
/// @copydoc MemoryBlock::alignment
/// @note The memory alignment for the ports
uint64_t alignment() const noexcept override;

/// @brief Implementation of MemoryBlock::memoryAvailable
/// This will create the ports
/// @param [in] memory pointer to a valid memory location to place the mempools
void memoryAvailable(void* memory) noexcept override;

/// @brief Implementation of MemoryBlock::destroy
/// This will clean up the ports
void destroy() noexcept override;

/// @brief This function enables the access to the PortPool
/// @return an optional pointer to the underlying type, cxx::nullopt_t if value is not initialized
cxx::optional<PortPoolData*> portPool() const noexcept;

protected:
/// @copydoc MemoryBlock::memoryAvailable
/// @note This will create the ports at the location `memory` points to
void onMemoryAvailable(cxx::not_null<void*> memory) noexcept override;

/// @copydoc MemoryBlock::destroy
/// @note This will clean up the ports
void destroy() noexcept override;

private:
PortPoolData* m_portPoolData{nullptr};
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,17 +42,14 @@ class GenericMemoryBlock final : public MemoryBlock
GenericMemoryBlock& operator=(const GenericMemoryBlock&) = delete;
GenericMemoryBlock& operator=(GenericMemoryBlock&&) = delete;

/// @brief Implementation of MemoryBlock::size
/// @return the size of type T
/// @copydoc MemoryBlock::size()
/// @note The size of the underlying type T
uint64_t size() const noexcept override;

/// @brief Implementation of MemoryBlock::alignment
/// @return the alignment of type T
/// @copydoc MemoryBlock::alignment
/// @note The alignment of the underlying type T
uint64_t alignment() const noexcept override;

/// @brief Implementation of MemoryBlock::destroy
void destroy() noexcept override;

/// @brief A new element is constructed by forwarding the arguments to the constructor of T. If the MemoryBlock has
/// a value then the destructor of T is called.
/// @param [in] args are perfectly forwarded to the constructor of T to perform a placement new
Expand All @@ -63,6 +61,11 @@ class GenericMemoryBlock final : public MemoryBlock
/// @return an optional pointer to the underlying type, cxx::nullopt_t if value is not initialized
cxx::optional<T*> value() const noexcept;

protected:
/// @copydoc MemoryBlock::destroy
/// @note This will destroy the underlying type T
void destroy() noexcept override;

private:
T* m_value{nullptr};
};
Expand Down
16 changes: 10 additions & 6 deletions iceoryx_posh/include/iceoryx_posh/roudi/memory/memory_block.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,6 +17,7 @@
#ifndef IOX_POSH_ROUDI_MEMORY_MEMORY_BLOCK_HPP
#define IOX_POSH_ROUDI_MEMORY_MEMORY_BLOCK_HPP

#include "iceoryx_hoofs/cxx/helplets.hpp"
#include "iceoryx_hoofs/cxx/optional.hpp"

#include <cstdint>
Expand All @@ -34,6 +36,7 @@ class MemoryBlock

public:
MemoryBlock() noexcept = default;
virtual ~MemoryBlock() noexcept = default;

/// @note this is intentional not movable/copyable, since a pointer to the memory block is registered at a
/// MemoryProvider and therefore an instance of a MemoryBlock must be pinned to memory
Expand All @@ -52,19 +55,20 @@ class MemoryBlock
/// @return the alignment of the underlying data.
virtual uint64_t alignment() const noexcept = 0;

/// @brief This function provides the pointer to the requested memory.
/// @return an optional pointer to a memory block with the requested size and alignment if the memory is available,
/// otherwise a cxx::nullopt_t
cxx::optional<void*> memory() const noexcept;

protected:
/// @brief The MemoryProvider calls this either when MemoryProvider::destroy is called or in its destructor.
/// @note This function can be called multiple times. Make sure that the implementation can handle this.
virtual void destroy() noexcept = 0;

/// @brief This function is called once the memory is available and is therefore the earliest possibility to use the
/// memory.
/// @param [in] memory pointer to a valid memory block, the same one that the memory() member function would return
virtual void memoryAvailable(void* memory) noexcept;

/// @brief This function provides the pointer to the requested memory.
/// @return an optional pointer to a memory block with the requested size and alignment if the memory is available,
/// otherwise a cxx::nullopt_t
cxx::optional<void*> memory() const noexcept;
virtual void onMemoryAvailable(cxx::not_null<void*> memory) noexcept;

private:
void* m_memory{nullptr};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class MemoryProvider

public:
MemoryProvider() noexcept = default;
~MemoryProvider() noexcept;
virtual ~MemoryProvider() noexcept;

/// @note this is intentional not movable/copyable, since a pointer to the memory provider is registered at the
/// RouDiMemoryManager and therefore an instance of a MemoryProvider must be pinned to memory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -51,15 +52,12 @@ class PosixShmMemoryProvider : public MemoryProvider
PosixShmMemoryProvider& operator=(const PosixShmMemoryProvider&) = delete;

protected:
/// @brief Implementation of MemoryProvider::createMemory
/// @param [in] size is the size in bytes for the requested memory, the size should already be calculated according
/// to the alignment requirements
/// @param [in] alignment the required alignment for the memory
/// @return the pointer of the begin of the created memory, nullptr if the memory could not be created
/// @copydoc MemoryProvider::createMemory
/// @note This creates and maps a POSIX shared memory to the address space of the application
cxx::expected<void*, MemoryProviderError> createMemory(const uint64_t size, const uint64_t alignment) noexcept;

/// @brief Implementation of MemoryProvider::destroyMemory
/// @return a MemoryProviderError if the destruction failed, otherwise success
/// @copydoc MemoryProvider::destroyMemory
/// @note This closes and unmaps a POSIX shared memory
cxx::expected<MemoryProviderError> destroyMemory() noexcept;

private:
Expand Down
3 changes: 2 additions & 1 deletion iceoryx_posh/source/roudi/memory/memory_block.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -21,7 +22,7 @@ namespace iox
{
namespace roudi
{
void MemoryBlock::memoryAvailable(void* memory IOX_MAYBE_UNUSED) noexcept
void MemoryBlock::onMemoryAvailable(cxx::not_null<void*> memory IOX_MAYBE_UNUSED) noexcept
{
// nothing to do in the default implementation
}
Expand Down
2 changes: 1 addition & 1 deletion iceoryx_posh/source/roudi/memory/memory_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ void MemoryProvider::announceMemoryAvailable() noexcept
{
for (auto memoryBlock : m_memoryBlocks)
{
memoryBlock->memoryAvailable(memoryBlock->m_memory);
memoryBlock->onMemoryAvailable(memoryBlock->m_memory);
}

m_memoryAvailableAnnounced = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ uint64_t MemPoolCollectionMemoryBlock::alignment() const noexcept
return algorithm::max(static_cast<uint64_t>(alignof(mepoo::MemoryManager)), memPoolAlignment);
}

void MemPoolCollectionMemoryBlock::memoryAvailable(void* memory) noexcept
void MemPoolCollectionMemoryBlock::onMemoryAvailable(cxx::not_null<void*> memory) noexcept
{
posix::Allocator allocator(memory, size());
auto memoryManager = allocator.allocate(sizeof(mepoo::MemoryManager), alignof(mepoo::MemoryManager));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ uint64_t MemPoolSegmentManagerMemoryBlock::alignment() const noexcept
mepoo::MemPool::CHUNK_MEMORY_ALIGNMENT);
}

void MemPoolSegmentManagerMemoryBlock::memoryAvailable(void* memory) noexcept
void MemPoolSegmentManagerMemoryBlock::onMemoryAvailable(cxx::not_null<void*> memory) noexcept
{
posix::Allocator allocator(memory, size());
auto segmentManager = allocator.allocate(sizeof(mepoo::SegmentManager<>), alignof(mepoo::SegmentManager<>));
Expand Down
3 changes: 2 additions & 1 deletion iceoryx_posh/source/roudi/memory/port_pool_memory_block.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,7 +40,7 @@ uint64_t PortPoolMemoryBlock::alignment() const noexcept
return alignof(PortPoolData);
}

void PortPoolMemoryBlock::memoryAvailable(void* memory) noexcept
void PortPoolMemoryBlock::onMemoryAvailable(cxx::not_null<void*> memory) noexcept
{
m_portPoolData = new (memory) PortPoolData;
}
Expand Down
7 changes: 4 additions & 3 deletions iceoryx_posh/test/mocks/roudi_memory_block_mock.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -36,9 +37,9 @@ class MemoryBlockMock final : public iox::roudi::MemoryBlock
return alignmentMock();
}

void memoryAvailable(void* memory) noexcept override
void onMemoryAvailable(iox::cxx::not_null<void*> memory) noexcept override
{
memoryAvailableMock(memory);
onMemoryAvailableMock(memory);
}

void destroy() noexcept override
Expand All @@ -48,7 +49,7 @@ class MemoryBlockMock final : public iox::roudi::MemoryBlock

MOCK_CONST_METHOD0(sizeMock, uint64_t());
MOCK_CONST_METHOD0(alignmentMock, uint64_t());
MOCK_METHOD1(memoryAvailableMock, void(void*));
MOCK_METHOD1(onMemoryAvailableMock, void(iox::cxx::not_null<void*>));
MOCK_METHOD0(destroyMock, void());
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,17 +177,15 @@ TEST_F(GenericMemoryBlock_NonTrivial_Test, MultipleEmplaceValue)
EXPECT_THAT(emplaceResult.value()->m_data, Eq(EXPECTED_VALUE));
}

TEST_F(GenericMemoryBlock_NonTrivial_Test, DestroyWithoutCreate)
TEST_F(GenericMemoryBlock_NonTrivial_Test, RunDestructorWithoutCreate)
{
sut.destroy();
/// @note we just expect to not terminate
}

TEST_F(GenericMemoryBlock_NonTrivial_Test, DestroyWithoutEmplace)
TEST_F(GenericMemoryBlock_NonTrivial_Test, RunDestructorWithoutEmplace)
{
IOX_DISCARD_RESULT(memoryProvider.addMemoryBlock(&sut));
IOX_DISCARD_RESULT(memoryProvider.create());
sut.destroy();
/// @note we just expect to not terminate
}

Expand All @@ -199,7 +197,7 @@ TEST_F(GenericMemoryBlock_NonTrivial_Test, DestroyWithEmplace)
EXPECT_THAT(sut.emplace(EXPECTED_VALUE).value()->m_data, EXPECTED_VALUE);
EXPECT_THAT(NonTrivialClass::s_constructorCounter, Eq(1u));

sut.destroy();
IOX_DISCARD_RESULT(memoryProvider.destroy());

EXPECT_THAT(sut.value().has_value(), Eq(false));
EXPECT_THAT(NonTrivialClass::s_destructorCounter, Eq(1u));
Expand All @@ -212,12 +210,12 @@ TEST_F(GenericMemoryBlock_NonTrivial_Test, RepetitiveDestroyWithEmplace)
IOX_DISCARD_RESULT(memoryProvider.create());
sut.emplace(EXPECTED_VALUE);

sut.destroy();
IOX_DISCARD_RESULT(memoryProvider.destroy());

EXPECT_THAT(sut.value().has_value(), Eq(false));

sut.destroy();
sut.destroy();
IOX_DISCARD_RESULT(memoryProvider.destroy());
IOX_DISCARD_RESULT(memoryProvider.destroy());

EXPECT_THAT(NonTrivialClass::s_destructorCounter, Eq(1u));
}
Expand Down
Loading