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
This commit is contained in:
Dennis Klein 2022-04-10 05:30:17 +02:00
parent 7e8e1db2e6
commit 22814cd914
3 changed files with 49 additions and 52 deletions

View File

@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * GNU Lesser General Public Licence (LGPL) version 3, *
@ -93,7 +93,7 @@ struct Receiver : fair::mq::Device
unordered_map<uint16_t, TFBuffer> fBuffer; unordered_map<uint16_t, TFBuffer> fBuffer;
unordered_set<uint16_t> fDiscardedSet; unordered_set<uint16_t> fDiscardedSet;
int fNumSenders = 0; unsigned int fNumSenders = 0;
int fBufferTimeoutInMs = 5000; int fBufferTimeoutInMs = 5000;
int fMaxTimeframes = 0; int fMaxTimeframes = 0;
int fTimeframeCounter = 0; int fTimeframeCounter = 0;

View File

@ -9,79 +9,76 @@
#ifndef FAIR_MQ_PARTS_H #ifndef FAIR_MQ_PARTS_H
#define FAIR_MQ_PARTS_H #define FAIR_MQ_PARTS_H
#include <fairmq/Message.h> #include <algorithm> // std::move
#include <memory> // unique_ptr #include <fairmq/Message.h> // fair::mq::MessagePtr
#include <vector> #include <iterator> // std::back_inserter
#include <utility> // std::move, std::forward
#include <vector> // std::vector
namespace fair::mq { 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 /// Message, used for sending multi-part messages
class Parts struct Parts
{ {
private:
using container = std::vector<MessagePtr>; using container = std::vector<MessagePtr>;
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() noexcept(noexcept(container())) = default;
Parts() = default;
Parts(const Parts&) = delete; Parts(const Parts&) = delete;
Parts(Parts&&) = default;
template<typename... Ts>
Parts(Ts&&... messages) { AddPart(std::forward<Ts>(messages)...); }
Parts& operator=(const Parts&) = delete; Parts& operator=(const Parts&) = delete;
Parts(Parts&&) = default;
Parts& operator=(Parts&&) = default; Parts& operator=(Parts&&) = default;
~Parts() = default; ~Parts() = default;
/// Adds part (Message) to the container template<typename... Ps>
/// @param msg message pointer (for example created with NewMessage() method of Device) Parts(Ps&&... parts)
void AddPart(Message* msg) { fParts.push_back(MessagePtr(msg)); } {
AddPart(std::forward<Ps>(parts)...);
}
/// Adds part to the container (move) void AddPart(MessagePtr msg) { fParts.push_back(std::move(msg)); }
/// @param msg unique pointer to Message
/// rvalue ref (move required when passing argument)
void AddPart(MessagePtr&& msg) { fParts.push_back(std::move(msg)); }
/// Add variable list of parts to the container (move)
template<typename... Ts> template<typename... Ts>
void AddPart(MessagePtr&& first, Ts&&... remaining) void AddPart(MessagePtr first, Ts&&... remaining)
{ {
AddPart(std::move(first)); AddPart(std::move(first));
AddPart(std::forward<Ts>(remaining)...); AddPart(std::forward<Ts>(remaining)...);
} }
/// Add content of another object by move void AddPart(Parts parts)
void AddPart(Parts&& other)
{ {
container parts = std::move(other.fParts); if (fParts.empty()) {
for (auto& part : parts) { fParts = std::move(parts.fParts);
fParts.push_back(std::move(part)); } 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) reference operator[](size_type index) { return fParts[index]; }
/// @param index container index const_reference operator[](size_type index) const { return fParts[index]; }
Message& operator[](const int index) { return *(fParts[index]); }
/// Get reference to unique pointer to part in the container at index (with bounds check) reference At(size_type index) { return fParts.at(index); }
/// @param index container index const_reference At(size_type index) const { return fParts.at(index); }
MessagePtr& At(const int index) { return fParts.at(index); }
// ref version size_type Size() const noexcept { return fParts.size(); }
Message& AtRef(const int index) { return *(fParts.at(index)); } bool Empty() const noexcept { return fParts.empty(); }
void Clear() noexcept { fParts.clear(); }
/// Get number of parts in the container // range access
/// @return number of parts in the container iterator begin() noexcept { return fParts.begin(); }
int Size() const { return fParts.size(); } 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; 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(); }
}; };
} // namespace fair::mq } // namespace fair::mq

View File

@ -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 * * This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, * * 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 for (unsigned int j = 0; j < GetNumSubChannels(fOutChannelNames.at(i)); ++j) { // all subChannels in a channel
Parts parts; Parts parts;
for (int k = 0; k < payload.Size(); ++k) { for (unsigned int k = 0; k < payload.Size(); ++k) {
MessagePtr msgCopy(fTransportFactory->CreateMessage()); MessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload.AtRef(k)); msgCopy->Copy(*(payload.At(k)));
parts.AddPart(std::move(msgCopy)); 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 for (unsigned int i = 0; i < lastChannelSize - 1; ++i) { // iterate over all except last subChannels of the last channel
Parts parts; Parts parts;
for (int k = 0; k < payload.Size(); ++k) { for (unsigned int k = 0; k < payload.Size(); ++k) {
MessagePtr msgCopy(fTransportFactory->CreateMessage()); MessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload.AtRef(k)); msgCopy->Copy(*(payload.At(k)));
parts.AddPart(std::move(msgCopy)); parts.AddPart(std::move(msgCopy));
} }