ChimeraTK-ApplicationCore 04.06.00
Loading...
Searching...
No Matches
ArrayAccessor.h
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#pragma once
4
5#include "Application.h"
7
8#include <ChimeraTK/OneDRegisterAccessor.h>
9#include <ChimeraTK/SystemTags.h>
10
11#include <boost/smart_ptr/shared_ptr.hpp>
12#include <boost/thread.hpp>
13
14#include <string>
15
16namespace ChimeraTK {
17
18 /********************************************************************************************************************/
19
23 template<typename UserType>
24 class ArrayAccessor : public ChimeraTK::OneDRegisterAccessor<UserType>,
25 public InversionOfControlAccessor<ArrayAccessor<UserType>> {
26 public:
28 void replace(const ChimeraTK::NDRegisterAccessorAbstractor<UserType>& newAccessor) = delete;
31 using ChimeraTK::OneDRegisterAccessor<UserType>::operator=;
32
35
38
39 bool write(ChimeraTK::VersionNumber versionNumber) = delete;
40 bool writeDestructively(ChimeraTK::VersionNumber versionNumber) = delete;
42 const std::vector<UserType>& newValue, VersionNumber versionNumber, DataValidity validity) = delete;
43 void setAndWrite(const std::vector<UserType>& newValue, VersionNumber versionNumber) = delete;
44
45 bool write();
46
48
49 void writeIfDifferent(const std::vector<UserType>& newValue);
50
51 void setAndWrite(const std::vector<UserType>& newValue);
52
53 using value_type = UserType;
54
55 protected:
56 friend class InversionOfControlAccessor<ArrayAccessor<UserType>>;
57
58 ArrayAccessor(Module* owner, const std::string& name, VariableDirection direction, std::string unit,
59 size_t nElements, UpdateMode mode, const std::string& description,
60 const std::unordered_set<std::string>& tags = {});
61
63 ArrayAccessor() = default;
64 };
65
66 /********************************************************************************************************************/
67
69 template<typename UserType>
70 struct ArrayPushInput : public ArrayAccessor<UserType> {
71 ArrayPushInput(Module* owner, const std::string& name, std::string unit, size_t nElements,
72 const std::string& description, const std::unordered_set<std::string>& tags = {});
73 ArrayPushInput() = default;
74 using ArrayAccessor<UserType>::operator=;
75 };
76
77 /********************************************************************************************************************/
78
80 template<typename UserType>
81 struct ArrayPollInput : public ArrayAccessor<UserType> {
82 ArrayPollInput(Module* owner, const std::string& name, std::string unit, size_t nElements,
83 const std::string& description, const std::unordered_set<std::string>& tags = {});
84 ArrayPollInput() = default;
85 void read() { this->readLatest(); }
86 using ArrayAccessor<UserType>::operator=;
87 };
88
89 /********************************************************************************************************************/
90
92 template<typename UserType>
93 struct ArrayOutput : public ArrayAccessor<UserType> {
94 ArrayOutput(Module* owner, const std::string& name, std::string unit, size_t nElements,
95 const std::string& description, const std::unordered_set<std::string>& tags = {});
96 ArrayOutput() = default;
97 using ArrayAccessor<UserType>::operator=;
98 };
99
100 /********************************************************************************************************************/
101
104 template<typename UserType>
105 struct ArrayPushInputWB : public ArrayAccessor<UserType> {
106 ArrayPushInputWB(Module* owner, const std::string& name, std::string unit, size_t nElements,
107 const std::string& description, const std::unordered_set<std::string>& tags = {});
108 ArrayPushInputWB() = default;
109 using ArrayAccessor<UserType>::operator=;
110 };
111
112 /********************************************************************************************************************/
113
116 template<typename UserType>
117 struct ArrayOutputPushRB : public ArrayAccessor<UserType> {
118 ArrayOutputPushRB(Module* owner, const std::string& name, std::string unit, size_t nElements,
119 const std::string& description, const std::unordered_set<std::string>& tags = {});
120 ArrayOutputPushRB() = default;
121 using ArrayAccessor<UserType>::operator=;
122 };
123
124 /********************************************************************************************************************/
125
127 template<typename UserType>
128 struct ArrayOutputRB : public ArrayAccessor<UserType> {
129 [[deprecated]] ArrayOutputRB(Module* owner, const std::string& name, std::string unit, size_t nElements,
130 const std::string& description, const std::unordered_set<std::string>& tags = {});
131 ArrayOutputRB() = default;
132 using ArrayAccessor<UserType>::operator=;
133 };
134
135 /********************************************************************************************************************/
136
137 template<typename UserType>
138 struct ArrayOutputReverseRecovery : public ArrayAccessor<UserType> {
139 ArrayOutputReverseRecovery(Module* owner, const std::string& name, std::string unit, size_t nElements,
140 const std::string& description, const std::unordered_set<std::string>& tags = {});
142 using ArrayAccessor<UserType>::operator=;
143 };
144 /********************************************************************************************************************/
145 /********************************************************************************************************************/
146 /* Implementations below this point */
147 /********************************************************************************************************************/
148 /********************************************************************************************************************/
149
150 template<typename UserType>
154
155 /********************************************************************************************************************/
156
157 template<typename UserType>
159 // Having a move-assignment operator is required to use the move-assignment
160 // operator of a module containing an accessor.
161 InversionOfControlAccessor<ArrayAccessor<UserType>>::replace(std::move(other));
162 return *this;
163 }
164
165 /********************************************************************************************************************/
166
167 template<typename UserType>
169 auto versionNumber = this->getOwner()->getCurrentVersionNumber();
170 bool dataLoss = ChimeraTK::OneDRegisterAccessor<UserType>::write(versionNumber);
171 if(dataLoss) {
172 Application::incrementDataLossCounter(this->_node.getQualifiedName());
173 }
174 return dataLoss;
175 }
176
177 /********************************************************************************************************************/
178
179 template<typename UserType>
181 auto versionNumber = this->getOwner()->getCurrentVersionNumber();
182 bool dataLoss = ChimeraTK::OneDRegisterAccessor<UserType>::writeDestructively(versionNumber);
183 if(dataLoss) {
184 Application::incrementDataLossCounter(this->_node.getQualifiedName());
185 }
186 return dataLoss;
187 }
188
189 /********************************************************************************************************************/
190
191 template<typename UserType>
192 void ArrayAccessor<UserType>::writeIfDifferent(const std::vector<UserType>& newValue) {
193 // Need to get to the MetaDataPropagatingRegisterDecorator to obtain the last written data validity for this PV.
194 // The dynamic_cast is ok, since the MetaDataPropagatingRegisterDecorator is always the outermost accessor, cf.
195 // the data validity propagation specification, Section 2.5.1.
196 auto* targetMetaDataPropagatingDecorator =
197 dynamic_cast<MetaDataPropagatingRegisterDecorator<UserType>*>(this->get());
198 assert(targetMetaDataPropagatingDecorator != nullptr);
199
200 // In contrast to OneDRegisterAccessor::writeIfDifferent(), we must not set the data validity on the target
201 // accessor, since that would be interpreted by the MetaDataPropagatingRegisterDecorator as an application-induced
202 // forced fault state. This would result in invalidity lock-ups if this happens in a circular network. Hence the
203 // comparison of the data validity must also be done against the validity of the decorator's target accessor which
204 // corresponds to the last written data validity for this PV.
205 if(!std::equal(newValue.begin(), newValue.end(), this->get()->accessChannel(0).begin()) ||
206 this->getVersionNumber() == VersionNumber(nullptr) ||
207 targetMetaDataPropagatingDecorator->getTargetValidity() != this->getOwner()->getDataValidity()) {
208 setAndWrite(newValue);
209 }
210 }
211
212 /********************************************************************************************************************/
213
214 template<typename UserType>
215 void ArrayAccessor<UserType>::setAndWrite(const std::vector<UserType>& newValue) {
216 operator=(newValue);
217 this->write();
218 }
219
220 /********************************************************************************************************************/
221
222 template<typename UserType>
223 ArrayAccessor<UserType>::ArrayAccessor(Module* owner, const std::string& name, VariableDirection direction,
224 std::string unit, size_t nElements, UpdateMode mode, const std::string& description,
225 const std::unordered_set<std::string>& tags)
227 owner, name, direction, unit, nElements, mode, description, &typeid(UserType), tags) {}
228
229 /********************************************************************************************************************/
230 /********************************************************************************************************************/
231
232 template<typename UserType>
233 ArrayPushInput<UserType>::ArrayPushInput(Module* owner, const std::string& name, std::string unit, size_t nElements,
234 const std::string& description, const std::unordered_set<std::string>& tags)
235 : ArrayAccessor<UserType>(
236 owner, name, {VariableDirection::consuming, false}, unit, nElements, UpdateMode::push, description, tags) {}
237
238 /********************************************************************************************************************/
239 /********************************************************************************************************************/
240
241 template<typename UserType>
242 ArrayPollInput<UserType>::ArrayPollInput(Module* owner, const std::string& name, std::string unit, size_t nElements,
243 const std::string& description, const std::unordered_set<std::string>& tags)
244 : ArrayAccessor<UserType>(
245 owner, name, {VariableDirection::consuming, false}, unit, nElements, UpdateMode::poll, description, tags) {}
246
247 /********************************************************************************************************************/
248 /********************************************************************************************************************/
249
250 template<typename UserType>
251 ArrayOutput<UserType>::ArrayOutput(Module* owner, const std::string& name, std::string unit, size_t nElements,
252 const std::string& description, const std::unordered_set<std::string>& tags)
253 : ArrayAccessor<UserType>(
254 owner, name, {VariableDirection::feeding, false}, unit, nElements, UpdateMode::push, description, tags) {}
255
256 /********************************************************************************************************************/
257 /********************************************************************************************************************/
258
259 template<typename UserType>
260 ArrayPushInputWB<UserType>::ArrayPushInputWB(Module* owner, const std::string& name, std::string unit,
261 size_t nElements, const std::string& description, const std::unordered_set<std::string>& tags)
262 : ArrayAccessor<UserType>(
263 owner, name, {VariableDirection::consuming, true}, unit, nElements, UpdateMode::push, description, tags) {}
264
265 /********************************************************************************************************************/
266 /********************************************************************************************************************/
267
268 template<typename UserType>
269 ArrayOutputPushRB<UserType>::ArrayOutputPushRB(Module* owner, const std::string& name, std::string unit,
270 size_t nElements, const std::string& description, const std::unordered_set<std::string>& tags)
271 : ArrayAccessor<UserType>(
272 owner, name, {VariableDirection::feeding, true}, unit, nElements, UpdateMode::push, description, tags) {}
273
274 /********************************************************************************************************************/
275 /********************************************************************************************************************/
276
277 template<typename UserType>
278 ArrayOutputRB<UserType>::ArrayOutputRB(Module* owner, const std::string& name, std::string unit, size_t nElements,
279 const std::string& description, const std::unordered_set<std::string>& tags)
280 : ArrayAccessor<UserType>(
281 owner, name, {VariableDirection::feeding, true}, unit, nElements, UpdateMode::push, description, tags) {}
282
283 /********************************************************************************************************************/
284 /********************************************************************************************************************/
285
286 template<typename UserType>
288 std::string unit, size_t nElements, const std::string& description, const std::unordered_set<std::string>& tags)
289 : ArrayAccessor<UserType>(
290 owner, name, {VariableDirection::feeding, true}, unit, nElements, UpdateMode::push, description, tags) {
291 this->addTag(ChimeraTK::SystemTags::reverseRecovery);
292 }
293
294 /********************************************************************************************************************/
295 /********************************************************************************************************************/
296
297} /* namespace ChimeraTK */
static void incrementDataLossCounter(const std::string &name)
Increment counter for how many write() operations have overwritten unread data.
Accessor for array variables (i.e.
void writeIfDifferent(const std::vector< UserType > &newValue, VersionNumber versionNumber, DataValidity validity)=delete
ArrayAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit, size_t nElements, UpdateMode mode, const std::string &description, const std::unordered_set< std::string > &tags={})
ArrayAccessor()=default
Default constructor creates a dysfunctional accessor (to be assigned with a real accessor later)
ArrayAccessor(ArrayAccessor< UserType > &&other) noexcept
Move constructor.
void replace(const ChimeraTK::NDRegisterAccessorAbstractor< UserType > &newAccessor)=delete
ArrayAccessor< UserType > & operator=(ArrayAccessor< UserType > &&other) noexcept
Move assignment.
ArrayAccessor< UserType > & operator=(ArrayAccessor< UserType > &other)=delete
bool write(ChimeraTK::VersionNumber versionNumber)=delete
void writeIfDifferent(const std::vector< UserType > &newValue)
void setAndWrite(const std::vector< UserType > &newValue, VersionNumber versionNumber)=delete
bool writeDestructively(ChimeraTK::VersionNumber versionNumber)=delete
Convenience class for input array accessors with UpdateMode::push.
ArrayPushInput(Module *owner, const std::string &name, std::string unit, size_t nElements, const std::string &description, const std::unordered_set< std::string > &tags={})
Convenience class for input array accessors with return channel ("write back") and UpdateMode::push.
Adds features required for inversion of control to an accessor.
NDRegisterAccessorDecorator which propagates meta data attached to input process variables through th...
Base class for ApplicationModule and DeviceModule, to have a common interface for these module types.
Definition Module.h:21
Class describing a node of a variable network.
InvalidityTracer application module.
UpdateMode
Enum to define the update mode of variables.
Definition Flags.h:31
Convenience class for output array accessors (always UpdateMode::push)
ArrayOutput(Module *owner, const std::string &name, std::string unit, size_t nElements, const std::string &description, const std::unordered_set< std::string > &tags={})
Convenience class for output array accessors with return channel ("read back") (always UpdateMode::pu...
Deprecated, do not use.
Convenience class for input array accessors with UpdateMode::poll.
ArrayPollInput(Module *owner, const std::string &name, std::string unit, size_t nElements, const std::string &description, const std::unordered_set< std::string > &tags={})
Struct to define the direction of variables.
Definition Flags.h:13