-
Notifications
You must be signed in to change notification settings - Fork 402
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
iox-#25: first version of ChunkSender and first tests
Signed-off-by: Poehnl Michael (CC-AD/ESW1) <[email protected]>
- Loading branch information
Poehnl Michael (CC-AD/ESW1)
committed
Mar 29, 2020
1 parent
731bb84
commit c5d5675
Showing
13 changed files
with
654 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
iceoryx_posh/include/iceoryx_posh/internal/popo/building_blocks/chunk_sender.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright (c) 2020 by Robert Bosch GmbH. 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. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://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. | ||
|
||
#ifndef IOX_POSH_POPO_CHUNK_SENDER_HPP_ | ||
#define IOX_POSH_POPO_CHUNK_SENDER_HPP_ | ||
|
||
#include "iceoryx_posh/internal/mepoo/shared_chunk.hpp" | ||
#include "iceoryx_posh/internal/popo/building_blocks/chunk_distributor.hpp" | ||
#include "iceoryx_posh/internal/popo/building_blocks/chunk_sender_data.hpp" | ||
#include "iceoryx_posh/mepoo/chunk_header.hpp" | ||
#include "iceoryx_utils/cxx/expected.hpp" | ||
|
||
namespace iox | ||
{ | ||
namespace popo | ||
{ | ||
/// @brief error which can occur in the VariantQueue | ||
enum class ChunkSenderError | ||
{ | ||
RUNNING_OUT_OF_CHUNKS, | ||
TOO_MANY_CHUKS_ALLOCATED_IN_PARALLEL | ||
}; | ||
|
||
/// @brief The ChunkSender is a building block of the shared memory communication infrastructure. It extends | ||
/// the functionality of a ChunkDistributor with the abililty to allocate and free memory chunks. | ||
/// For getting chunks of memory the MemoryManger is used. Together with the ChunkReceiver, they are the next | ||
/// abstraction layer on top of ChunkDistributor and ChunkQueue. The ChunkSender holds the ownership of the | ||
/// SharedChunks and does a bookkeeping which chunks are currently passed to the user side. | ||
class ChunkSender : public ChunkDistributor | ||
{ | ||
public: | ||
using MemberType_t = ChunkSenderData; | ||
|
||
ChunkSender(MemberType_t* const chunkDistributorDataPtr) noexcept; | ||
|
||
ChunkSender(const ChunkSender& other) = delete; | ||
ChunkSender& operator=(const ChunkSender&) = delete; | ||
ChunkSender(ChunkSender&& rhs) = default; | ||
ChunkSender& operator=(ChunkSender&& rhs) = default; | ||
~ChunkSender() = default; | ||
|
||
/// @brief Allocate a chunk, the ownerhip of the SharedChunk remains in the ChunkSender for being able to cleanup if | ||
/// the user process disappears | ||
/// @param[in] payloadSize, size of the user paylaod without additional headers | ||
/// @return on success pointer to a ChunkHeader which can be used to access the payload and header fields, error if | ||
/// not | ||
cxx::expected<mepoo::ChunkHeader*, ChunkSenderError> allocate(const uint32_t payloadSize) noexcept; | ||
|
||
/// @brief Free an allocated chunk without sending it | ||
/// @param[in] chunkHeader, pointer to the ChunkHeader to free | ||
void free(mepoo::ChunkHeader* const chunkHeader) noexcept; | ||
|
||
/// @brief Send an allocated chunk to all connected ChunkQueue | ||
/// @param[in] chunkHeader, pointer to the ChunkHeader to send | ||
void send(mepoo::ChunkHeader* const chunkHeader) noexcept; | ||
|
||
/// @brief Push an allocated chunk to the history without sending it | ||
/// @param[in] chunkHeader, pointer to the ChunkHeader to push to the history | ||
void pushToHistory(mepoo::ChunkHeader* const chunkHeader) noexcept; | ||
|
||
/// @brief Release all the chunks that are currently held. Caution: Only call this if the user process is no more | ||
/// running E.g. This cleans up chunks that were held by a user process that died unexpectetly, for avoiding lost | ||
/// chunks in the system | ||
void cleanup() noexcept; | ||
|
||
private: | ||
/// @brief Get the SharedChunk from the provided ChunkHeader and do all that is required to send the chunk | ||
/// @param[in] chunkHeader of the chunk that shall be send | ||
/// @param[in][out] chunk that corresponds to the chunk header | ||
/// @return true if there was a matching chunk with this header, false if not | ||
bool getChunkReadyForSend(mepoo::ChunkHeader* chunkHeader, mepoo::SharedChunk& chunk) noexcept; | ||
|
||
const MemberType_t* getMembers() const noexcept; | ||
MemberType_t* getMembers() noexcept; | ||
}; | ||
|
||
} // namespace popo | ||
} // namespace iox | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
iceoryx_posh/source/popo/building_blocks/chunk_sender.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// Copyright (c) 2020 by Robert Bosch GmbH. 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. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://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 "iceoryx_posh/internal/popo/building_blocks/chunk_sender.hpp" | ||
#include "iceoryx_utils/error_handling/error_handling.hpp" | ||
|
||
namespace iox | ||
{ | ||
namespace popo | ||
{ | ||
ChunkSender::ChunkSender(MemberType_t* const chunkSenderDataPtr) noexcept | ||
: ChunkDistributor(chunkSenderDataPtr) | ||
{ | ||
} | ||
|
||
const ChunkSender::MemberType_t* ChunkSender::getMembers() const noexcept | ||
{ | ||
return reinterpret_cast<const MemberType_t*>(ChunkDistributor::getMembers()); | ||
} | ||
|
||
ChunkSender::MemberType_t* ChunkSender::getMembers() noexcept | ||
{ | ||
return reinterpret_cast<MemberType_t*>(ChunkDistributor::getMembers()); | ||
} | ||
|
||
cxx::expected<mepoo::ChunkHeader*, ChunkSenderError> ChunkSender::allocate(const uint32_t payloadSize) noexcept | ||
{ | ||
// use the chunk stored in m_lastChunk if there is one, there is no other owner and the new payload fits in this | ||
// chunk | ||
if (getMembers()->m_lastChunk && getMembers()->m_lastChunk.hasNoOtherOwners() | ||
&& getMembers()->m_lastChunk.getChunkHeader()->m_info.m_usedSizeOfChunk | ||
>= getMembers()->m_memoryMgr->sizeWithChunkHeaderStruct(payloadSize)) | ||
{ | ||
if (getMembers()->m_chunksInUse.insert(getMembers()->m_lastChunk)) | ||
{ | ||
getMembers()->m_lastChunk.getChunkHeader()->m_info.m_payloadSize = payloadSize; | ||
getMembers()->m_lastChunk.getChunkHeader()->m_info.m_usedSizeOfChunk = | ||
getMembers()->m_memoryMgr->sizeWithChunkHeaderStruct(payloadSize); | ||
return cxx::success<mepoo::ChunkHeader*>(getMembers()->m_lastChunk.getChunkHeader()); | ||
} | ||
else | ||
{ | ||
return cxx::error<ChunkSenderError>(ChunkSenderError::TOO_MANY_CHUKS_ALLOCATED_IN_PARALLEL); | ||
} | ||
} | ||
else | ||
{ | ||
// START of critical section, chunk will be lost if process gets hard terminated in between | ||
// get a new chunk | ||
mepoo::SharedChunk chunk = getMembers()->m_memoryMgr->getChunk(payloadSize); | ||
|
||
if (chunk) | ||
{ | ||
// if the application allocated too much chunks, return no more chunks | ||
if (getMembers()->m_chunksInUse.insert(chunk)) | ||
{ | ||
// STOP of critical section, chunk will be lost if process gets hard terminated in between | ||
return cxx::success<mepoo::ChunkHeader*>(chunk.getChunkHeader()); | ||
} | ||
else | ||
{ | ||
// release the allocated chunk | ||
chunk = nullptr; | ||
return cxx::error<ChunkSenderError>(ChunkSenderError::TOO_MANY_CHUKS_ALLOCATED_IN_PARALLEL); | ||
} | ||
} | ||
else | ||
{ | ||
return cxx::error<ChunkSenderError>(ChunkSenderError::RUNNING_OUT_OF_CHUNKS); | ||
} | ||
} | ||
} | ||
|
||
void ChunkSender::free(mepoo::ChunkHeader* const chunkHeader) noexcept | ||
{ | ||
mepoo::SharedChunk chunk(nullptr); | ||
if (!getMembers()->m_chunksInUse.remove(chunkHeader, chunk)) | ||
{ | ||
errorHandler(Error::kPOPO__CHUNK_SENDER_INVALID_CHUNK_TO_FREE_FROM_USER, nullptr, ErrorLevel::SEVERE); | ||
} | ||
} | ||
|
||
void ChunkSender::send(mepoo::ChunkHeader* const chunkHeader) noexcept | ||
{ | ||
mepoo::SharedChunk chunk(nullptr); | ||
// START of critical section, chunk will be lost if process gets hard terminated in between | ||
if (getChunkReadyForSend(chunkHeader, chunk)) | ||
{ | ||
this->deliverToAllStoredQueues(chunk); | ||
getMembers()->m_lastChunk = chunk; | ||
} | ||
// STOP of critical section, chunk will be lost if process gets hard terminated in between | ||
} | ||
|
||
void ChunkSender::pushToHistory(mepoo::ChunkHeader* const chunkHeader) noexcept | ||
{ | ||
mepoo::SharedChunk chunk(nullptr); | ||
// START of critical section, chunk will be lost if process gets hard terminated in between | ||
if (getChunkReadyForSend(chunkHeader, chunk)) | ||
{ | ||
this->addToHistoryWithoutDelivery(chunk); | ||
getMembers()->m_lastChunk = chunk; | ||
} | ||
// STOP of critical section, chunk will be lost if process gets hard terminated in between | ||
} | ||
|
||
bool ChunkSender::getChunkReadyForSend(mepoo::ChunkHeader* chunkHeader, mepoo::SharedChunk& chunk) noexcept | ||
{ | ||
if (getMembers()->m_chunksInUse.remove(chunkHeader, chunk)) | ||
{ | ||
auto& chunkInfo = chunk.getChunkHeader()->m_info; | ||
if (!chunkInfo.m_externalSequenceNumber_bl) | ||
{ | ||
chunkInfo.m_sequenceNumber = getMembers()->m_sequenceNumber; | ||
getMembers()->m_sequenceNumber++; | ||
} | ||
else | ||
{ | ||
getMembers()->m_sequenceNumber++; // for Introspection, else nobody updates. | ||
} | ||
return true; | ||
} | ||
else | ||
{ | ||
errorHandler(Error::kPOPO__CHUNK_SENDER_INVALID_CHUNK_TO_SEND_FROM_USER, nullptr, ErrorLevel::SEVERE); | ||
return false; | ||
} | ||
} | ||
|
||
void ChunkSender::cleanup() noexcept | ||
{ | ||
getMembers()->m_chunksInUse.cleanup(); | ||
this->clearHistory(); | ||
getMembers()->m_lastChunk = nullptr; | ||
} | ||
|
||
} // namespace popo | ||
} // namespace iox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.