From efd6523112f26e9ecfeb1661eecdfccf2b2f3d15 Mon Sep 17 00:00:00 2001 From: Dennis Klein Date: Sun, 10 Apr 2022 05:30:17 +0200 Subject: [PATCH] feat(Parts)!: Refine and tweak * Optimize appending another Parts container * Remove redundant/verbose comments * Change r-value args to move-only types into l-value args for readability * BREAKING CHANGE: Remove `AtRef(int)` and `AddPart(Message*)` member functions * Add various const overloads * Add `Empty()` and `Clear()` member functions * Add `noexcept` where applicable --- examples/n-m/receiver.cxx | 4 +- fairmq/Parts.h | 87 ++++++++++++++++++------------------- fairmq/devices/Multiplier.h | 10 ++--- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/examples/n-m/receiver.cxx b/examples/n-m/receiver.cxx index 91913450..8e877b31 100644 --- a/examples/n-m/receiver.cxx +++ b/examples/n-m/receiver.cxx @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * Copyright (C) 2020-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * @@ -93,7 +93,7 @@ struct Receiver : fair::mq::Device unordered_map fBuffer; unordered_set fDiscardedSet; - int fNumSenders = 0; + unsigned int fNumSenders = 0; int fBufferTimeoutInMs = 5000; int fMaxTimeframes = 0; int fTimeframeCounter = 0; diff --git a/fairmq/Parts.h b/fairmq/Parts.h index a8f5811f..0b3976e0 100644 --- a/fairmq/Parts.h +++ b/fairmq/Parts.h @@ -9,79 +9,76 @@ #ifndef FAIR_MQ_PARTS_H #define FAIR_MQ_PARTS_H -#include -#include // unique_ptr -#include +#include // std::move +#include // fair::mq::MessagePtr +#include // std::back_inserter +#include // std::move, std::forward +#include // std::vector namespace fair::mq { -/// fair::mq::Parts is a lightweight convenience wrapper around a vector of unique pointers to +/// fair::mq::Parts is a lightweight move-only convenience wrapper around a vector of unique pointers to /// Message, used for sending multi-part messages -class Parts +struct Parts { - private: using container = std::vector; + using size_type = container::size_type; + using reference = container::reference; + using const_reference = container::const_reference; + using iterator = container::iterator; + using const_iterator = container::const_iterator; - public: - Parts() = default; + Parts() noexcept(noexcept(container())) = default; Parts(const Parts&) = delete; - Parts(Parts&&) = default; - template - Parts(Ts&&... messages) { AddPart(std::forward(messages)...); } Parts& operator=(const Parts&) = delete; + Parts(Parts&&) = default; Parts& operator=(Parts&&) = default; ~Parts() = default; - /// Adds part (Message) to the container - /// @param msg message pointer (for example created with NewMessage() method of Device) - void AddPart(Message* msg) { fParts.push_back(MessagePtr(msg)); } + template + Parts(Ps&&... parts) + { + AddPart(std::forward(parts)...); + } - /// Adds part to the container (move) - /// @param msg unique pointer to Message - /// rvalue ref (move required when passing argument) - void AddPart(MessagePtr&& msg) { fParts.push_back(std::move(msg)); } + void AddPart(MessagePtr msg) { fParts.push_back(std::move(msg)); } - /// Add variable list of parts to the container (move) template - void AddPart(MessagePtr&& first, Ts&&... remaining) + void AddPart(MessagePtr first, Ts&&... remaining) { AddPart(std::move(first)); AddPart(std::forward(remaining)...); } - /// Add content of another object by move - void AddPart(Parts&& other) + void AddPart(Parts parts) { - container parts = std::move(other.fParts); - for (auto& part : parts) { - fParts.push_back(std::move(part)); + if (fParts.empty()) { + fParts = std::move(parts.fParts); + } else { + fParts.reserve(parts.Size() + fParts.size()); + std::move(std::begin(parts), std::end(parts), std::back_inserter(fParts)); } } - /// Get reference to part in the container at index (without bounds check) - /// @param index container index - Message& operator[](const int index) { return *(fParts[index]); } + reference operator[](size_type index) { return fParts[index]; } + const_reference operator[](size_type index) const { return fParts[index]; } - /// Get reference to unique pointer to part in the container at index (with bounds check) - /// @param index container index - MessagePtr& At(const int index) { return fParts.at(index); } + reference At(size_type index) { return fParts.at(index); } + const_reference At(size_type index) const { return fParts.at(index); } - // ref version - Message& AtRef(const int index) { return *(fParts.at(index)); } + size_type Size() const noexcept { return fParts.size(); } + bool Empty() const noexcept { return fParts.empty(); } + void Clear() noexcept { fParts.clear(); } - /// Get number of parts in the container - /// @return number of parts in the container - int Size() const { return fParts.size(); } + // range access + iterator begin() noexcept { return fParts.begin(); } + const_iterator begin() const noexcept { return fParts.begin(); } + const_iterator cbegin() const noexcept { return fParts.cbegin(); } + iterator end() noexcept { return fParts.end(); } + const_iterator end() const noexcept { return fParts.end(); } + const_iterator cend() const noexcept { return fParts.cend(); } - container fParts; - - // forward container iterators - using iterator = container::iterator; - using const_iterator = container::const_iterator; - auto begin() -> decltype(fParts.begin()) { return fParts.begin(); } - auto end() -> decltype(fParts.end()) { return fParts.end(); } - auto cbegin() -> decltype(fParts.cbegin()) { return fParts.cbegin(); } - auto cend() -> decltype(fParts.cend()) { return fParts.cend(); } + container fParts{}; }; } // namespace fair::mq diff --git a/fairmq/devices/Multiplier.h b/fairmq/devices/Multiplier.h index fda65ac1..f899ecaf 100644 --- a/fairmq/devices/Multiplier.h +++ b/fairmq/devices/Multiplier.h @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * Copyright (C) 2014-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * @@ -71,9 +71,9 @@ class Multiplier : public Device for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel Parts parts; - for (int k = 0; k < payload.Size(); ++k) { + for (unsigned int k = 0; k < payload.Size(); ++k) { MessagePtr msgCopy(fTransportFactory->CreateMessage()); - msgCopy->Copy(payload.AtRef(k)); + msgCopy->Copy(*(payload.At(k))); parts.AddPart(std::move(msgCopy)); } @@ -86,9 +86,9 @@ class Multiplier : public Device for (unsigned int i = 0; i < lastChannelSize - 1; ++i) { // iterate over all except last subChannels of the last channel Parts parts; - for (int k = 0; k < payload.Size(); ++k) { + for (unsigned int k = 0; k < payload.Size(); ++k) { MessagePtr msgCopy(fTransportFactory->CreateMessage()); - msgCopy->Copy(payload.AtRef(k)); + msgCopy->Copy(*(payload.At(k))); parts.AddPart(std::move(msgCopy)); }