ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
FanOutPlugin.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#include "LNMAccessorPlugin.h"
7#include "TransferElement.h"
8
9#include <boost/algorithm/string/predicate.hpp>
10#include <boost/make_shared.hpp>
11
12namespace ChimeraTK::LNMBackend {
13
14 /********************************************************************************************************************/
15
17 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters)
18 : AccessorPlugin(info, pluginIndex) {
19 // extract parameters
20 for(const auto& [param, value] : parameters) {
21 if(boost::starts_with(param, "target")) {
22 _targets.push_back(value);
23 }
24 else {
25 throw ChimeraTK::logic_error("LogicalNameMappingBackend FanOutPlugin: Unknown parameter '" + param + "'.");
26 }
27 }
28 }
29
30 /********************************************************************************************************************/
31
33 if(!_info.writeable) {
34 throw ChimeraTK::logic_error("FanOutPlugin requires a writeable target register: " + _info.getRegisterName());
35 }
36
37 _info.readable = false;
40 }
41
42 /********************************************************************************************************************/
43 /********************************************************************************************************************/
44
45 template<typename UserType>
48 std::vector<boost::shared_ptr<NDRegisterAccessor<UserType>>> accs)
49 : ChimeraTK::NDRegisterAccessorDecorator<UserType, UserType>(target), _accs(std::move(accs)) {}
50
51 void doPreWrite(TransferType type, VersionNumber) override;
52 bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override;
53 bool doWriteTransferDestructively(ChimeraTK::VersionNumber versionNumber) override;
54 void doPostWrite(TransferType type, VersionNumber versionNumber) override;
55
56 [[nodiscard]] bool isReadOnly() const override { return false; }
57 [[nodiscard]] bool isReadable() const override { return false; }
58
60 using ChimeraTK::NDRegisterAccessorDecorator<UserType, UserType>::_target;
61
62 private:
63 std::vector<boost::shared_ptr<NDRegisterAccessor<UserType>>> _accs;
64 };
65
66 /********************************************************************************************************************/
67
68 template<typename UserType>
70 std::exception_ptr firstException{nullptr};
71
72 for(auto& acc : _accs) {
73 for(size_t i = 0; i < acc->getNumberOfChannels(); ++i) {
74 acc->accessChannel(i) = buffer_2D[i];
75 }
76 acc->setDataValidity(this->_dataValidity);
77 try {
78 acc->preWrite(type, versionNumber);
79 }
80 catch(...) {
81 if(!firstException) {
82 firstException = std::current_exception();
83 }
84 }
85 }
86
87 // the base class' doPreWrite must be called even if the other preWrites throw, otherwise our postWrite destroys the
88 // application buffer with its swap.
89 try {
91 }
92 catch(...) {
93 if(!firstException) {
94 firstException = std::current_exception();
95 }
96 }
97
98 // if any exception was thrown, re-throw the first one
99 if(firstException) {
100 std::rethrow_exception(firstException);
101 }
102 }
103
104 /********************************************************************************************************************/
105
106 template<typename UserType>
108 bool rv = false;
109
110 for(auto& acc : _accs) {
111 rv |= acc->writeTransfer(versionNumber);
112 }
113
115
116 return rv;
117 }
118
119 /********************************************************************************************************************/
120
121 template<typename UserType>
123 bool rv = false;
124
125 for(auto& acc : _accs) {
126 rv |= acc->writeTransferDestructively(versionNumber);
127 }
128
130
131 return rv;
132 }
133
134 /********************************************************************************************************************/
135
136 template<typename UserType>
138 for(auto& acc : _accs) {
139 acc->postWrite(type, versionNumber);
140 }
141
143 }
144
145 /********************************************************************************************************************/
146 /********************************************************************************************************************/
147
148 template<typename UserType, typename TargetType>
149 boost::shared_ptr<NDRegisterAccessor<UserType>> FanOutPlugin::decorateAccessor(
150 boost::shared_ptr<LogicalNameMappingBackend>& backend, boost::shared_ptr<NDRegisterAccessor<TargetType>>& target,
151 const UndecoratedParams&) {
152 if(!target->isWriteable()) {
153 throw ChimeraTK::logic_error(std::format("LogicalNameMappingBackend FanOutPlugin: Main target register "
154 "'{}' is not writeable.",
155 target->getName()));
156 }
157
158 if(target->getAccessModeFlags().has(AccessMode::raw)) {
160 std::format("LogicalNameMappingBackend FanOutPlugin: AccessMode::raw is not supported in register '{}'.",
161 target->getName()));
162 }
163
164 // create additional target accessors
165 std::vector<boost::shared_ptr<NDRegisterAccessor<TargetType>>> accs;
166 accs.reserve(_targets.size());
167 for(const auto& name : _targets) {
168 accs.push_back(backend->getRegisterAccessor<TargetType>(name, 0, 0, {}));
169 if(accs.back()->getNumberOfChannels() != target->getNumberOfChannels() ||
170 accs.back()->getNumberOfSamples() != target->getNumberOfSamples()) {
171 throw ChimeraTK::logic_error(std::format("LogicalNameMappingBackend FanOutPlugin: Shape of target register "
172 "'{}' does not match the shape of the main target {}.",
173 name, target->getName()));
174 }
175 if(!accs.back()->isWriteable()) {
176 throw ChimeraTK::logic_error(std::format("LogicalNameMappingBackend FanOutPlugin: Target register "
177 "'{}' is not writeable (main target: {}).",
178 name, target->getName()));
179 }
180 }
181
182 if constexpr(std::is_same<TargetType, UserType>::value) {
183 return boost::make_shared<FanOutPluginDecorator<UserType>>(target, std::move(accs));
184 }
185
186 assert(false);
187
188 return {};
189 }
190
191 /********************************************************************************************************************/
192
193} // namespace ChimeraTK::LNMBackend
void remove(AccessMode flag)
Remove the given flag from the set.
Definition AccessMode.cc:56
void setRawDataType(const DataType &d)
Set the raw data type.
LNMBackendRegisterInfo _info
RegisterInfo describing the the target register for which this plugin instance should work.
Base class for plugins that modify the behaviour of accessors in the logical name mapping backend.
FanOutPlugin(const LNMBackendRegisterInfo &info, size_t pluginIndex, const std::map< std::string, std::string > &parameters)
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
RegisterInfo structure for the LogicalNameMappingBackend.
RegisterPath getRegisterName() const override
Return full path name of the register (including modules)
AccessModeFlags supportedFlags
Supported AccessMode flags.
bool readable
Flag if the register is readable.
bool writeable
Flag if the register is writeable.
Base class for decorators of the NDRegisterAccessor.
bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override
Implementation version of writeTransfer().
bool doWriteTransferDestructively(ChimeraTK::VersionNumber versionNumber) override
Implementation version of writeTransferDestructively().
N-dimensional register accessor.
std::vector< UserType > & accessChannel(unsigned int channel)
Get or set register accessor's channel vector.
std::vector< std::vector< UserType > > buffer_2D
Buffer of converted data elements.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
Definition Exception.h:51
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
TransferType
Used to indicate the applicable operation on a Transferelement.
STL namespace.
void doPreWrite(TransferType type, VersionNumber) override
Backend specific implementation of preWrite().
bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override
Implementation version of writeTransfer().
void doPostWrite(TransferType type, VersionNumber versionNumber) override
Backend specific implementation of postWrite().
bool isReadable() const override
Check if transfer element is readable.
FanOutPluginDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< UserType > > &target, std::vector< boost::shared_ptr< NDRegisterAccessor< UserType > > > accs)
bool isReadOnly() const override
Check if transfer element is read only, i.e.
bool doWriteTransferDestructively(ChimeraTK::VersionNumber versionNumber) override
Implementation version of writeTransferDestructively().
Helper struct to hold extra parameters needed by some plugins, used in decorateAccessor()