ChimeraTK-ApplicationCore 04.06.00
Loading...
Searching...
No Matches
ScalarAccessor.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/ScalarRegisterAccessor.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
24 template<typename UserType>
25 class ScalarAccessor : public ChimeraTK::ScalarRegisterAccessor<UserType>,
26 public InversionOfControlAccessor<ScalarAccessor<UserType>> {
27 public:
29 void replace(const ChimeraTK::NDRegisterAccessorAbstractor<UserType>& newAccessor) = delete;
32 using ChimeraTK::ScalarRegisterAccessor<UserType>::operator=;
33
36
39
40 bool write(ChimeraTK::VersionNumber versionNumber) = delete;
41 bool writeDestructively(ChimeraTK::VersionNumber versionNumber) = delete;
42 void writeIfDifferent(UserType newValue, VersionNumber versionNumber, DataValidity validity) = delete;
43 void setAndWrite(UserType newValue, VersionNumber versionNumber) = delete;
44
45 bool write();
46
48
49 void writeIfDifferent(UserType newValue);
50
51 void setAndWrite(UserType newValue);
52
53 using value_type = UserType;
54
55 protected:
56 friend class InversionOfControlAccessor<ScalarAccessor<UserType>>;
57
58 ScalarAccessor(Module* owner, const std::string& name, VariableDirection direction, std::string unit,
59 UpdateMode mode, const std::string& description, const std::unordered_set<std::string>& tags = {});
60
63 ScalarAccessor() = default;
64 };
65
66 /********************************************************************************************************************/
67
69 template<typename UserType>
70 struct ScalarPushInput : public ScalarAccessor<UserType> {
71 ScalarPushInput(Module* owner, const std::string& name, std::string unit, const std::string& description,
72 const std::unordered_set<std::string>& tags = {});
74 using ScalarAccessor<UserType>::operator=;
75 };
76
77 /********************************************************************************************************************/
78
80 template<typename UserType>
81 struct ScalarPollInput : public ScalarAccessor<UserType> {
82 ScalarPollInput(Module* owner, const std::string& name, std::string unit, const std::string& description,
83 const std::unordered_set<std::string>& tags = {});
85 void read() { this->readLatest(); }
86 using ScalarAccessor<UserType>::operator=;
87 };
88
89 /********************************************************************************************************************/
90
92 template<typename UserType>
93 struct ScalarOutput : public ScalarAccessor<UserType> {
94 ScalarOutput(Module* owner, const std::string& name, std::string unit, const std::string& description,
95 const std::unordered_set<std::string>& tags = {});
96 ScalarOutput() : ScalarAccessor<UserType>() {}
97 using ScalarAccessor<UserType>::operator=;
98 };
99
100 /********************************************************************************************************************/
101
103 template<typename UserType>
104 struct ScalarPushInputWB : public ScalarAccessor<UserType> {
105 ScalarPushInputWB(Module* owner, const std::string& name, std::string unit, const std::string& description,
106 const std::unordered_set<std::string>& tags = {});
108 using ScalarAccessor<UserType>::operator=;
109 };
110
111 /********************************************************************************************************************/
112
114 template<typename UserType>
115 struct ScalarOutputPushRB : public ScalarAccessor<UserType> {
116 ScalarOutputPushRB(Module* owner, const std::string& name, std::string unit, const std::string& description,
117 const std::unordered_set<std::string>& tags = {});
119 using ScalarAccessor<UserType>::operator=;
120 };
121
122 /********************************************************************************************************************/
123
125 template<typename UserType>
126 struct ScalarOutputReverseRecovery : public ScalarAccessor<UserType> {
127 ScalarOutputReverseRecovery(Module* owner, const std::string& name, std::string unit,
128 const std::string& description, const std::unordered_set<std::string>& tags = {});
130 using ScalarAccessor<UserType>::operator=;
131 };
132 /********************************************************************************************************************/
133 /********************************************************************************************************************/
134 /* Implementations below this point */
135 /********************************************************************************************************************/
136 /********************************************************************************************************************/
137
138 template<typename UserType>
142
143 /********************************************************************************************************************/
144
145 template<typename UserType>
147 // Having a move-assignment operator is required to use the move-assignment
148 // operator of a module containing an accessor.
149 InversionOfControlAccessor<ScalarAccessor<UserType>>::replace(std::move(other));
150 return *this;
151 }
152
153 /********************************************************************************************************************/
154
155 template<typename UserType>
157 auto versionNumber = this->getOwner()->getCurrentVersionNumber();
158 bool dataLoss = ChimeraTK::ScalarRegisterAccessor<UserType>::write(versionNumber);
159 if(dataLoss) {
160 Application::incrementDataLossCounter(this->_node.getQualifiedName());
161 }
162 return dataLoss;
163 }
164
165 /********************************************************************************************************************/
166
167 template<typename UserType>
169 auto versionNumber = this->getOwner()->getCurrentVersionNumber();
170 bool dataLoss = ChimeraTK::ScalarRegisterAccessor<UserType>::writeDestructively(versionNumber);
171 if(dataLoss) {
172 Application::incrementDataLossCounter(this->_node.getQualifiedName());
173 }
174 return dataLoss;
175 }
176
177 /********************************************************************************************************************/
178
179 template<typename UserType>
181 // Need to get to the MetaDataPropagatingRegisterDecorator to obtain the last written data validity for this PV.
182 // The dynamic_cast is ok, since the MetaDataPropagatingRegisterDecorator is always the outermost accessor, cf.
183 // the data validity propagation specification, Section 2.5.1.
184 auto* targetMetaDataPropagatingDecorator =
185 dynamic_cast<MetaDataPropagatingRegisterDecorator<UserType>*>(this->get());
186 assert(targetMetaDataPropagatingDecorator != nullptr);
187
188 // In contrast to ScalarRegisterAccessor::writeIfDifferent(), we must not set the data validity on the target
189 // accessor, since that would be interpreted by the MetaDataPropagatingRegisterDecorator as an application-induced
190 // forced fault state. This would result in invalidity lock-ups if this happens in a circular network. Hence the
191 // comparison of the data validity must also be done against the validity of the decorator's target accessor which
192 // corresponds to the last written data validity for this PV.
193 if(this->get()->accessData(0, 0) != newValue || this->getVersionNumber() == VersionNumber(nullptr) ||
194 targetMetaDataPropagatingDecorator->getTargetValidity() != this->getOwner()->getDataValidity()) {
195 setAndWrite(newValue);
196 }
197 }
198
199 /********************************************************************************************************************/
200
201 template<typename UserType>
203 operator=(newValue);
204 this->write();
205 }
206
207 /********************************************************************************************************************/
208
209 template<typename UserType>
210 ScalarAccessor<UserType>::ScalarAccessor(Module* owner, const std::string& name, VariableDirection direction,
211 std::string unit, UpdateMode mode, const std::string& description, const std::unordered_set<std::string>& tags)
213 owner, name, direction, unit, 1, mode, description, &typeid(UserType), tags) {}
214
215 /********************************************************************************************************************/
216 /********************************************************************************************************************/
217
218 template<typename UserType>
219 ScalarPushInput<UserType>::ScalarPushInput(Module* owner, const std::string& name, std::string unit,
220 const std::string& description, const std::unordered_set<std::string>& tags)
221 : ScalarAccessor<UserType>(
222 owner, name, {VariableDirection::consuming, false}, unit, UpdateMode::push, description, tags) {}
223
224 /********************************************************************************************************************/
225 /********************************************************************************************************************/
226
227 template<typename UserType>
228 ScalarPollInput<UserType>::ScalarPollInput(Module* owner, const std::string& name, std::string unit,
229 const std::string& description, const std::unordered_set<std::string>& tags)
230 : ScalarAccessor<UserType>(
231 owner, name, {VariableDirection::consuming, false}, unit, UpdateMode::poll, description, tags) {}
232
233 /********************************************************************************************************************/
234 /********************************************************************************************************************/
235
236 template<typename UserType>
237 ScalarOutput<UserType>::ScalarOutput(Module* owner, const std::string& name, std::string unit,
238 const std::string& description, const std::unordered_set<std::string>& tags)
239 : ScalarAccessor<UserType>(
240 owner, name, {VariableDirection::feeding, false}, unit, UpdateMode::push, description, tags) {}
241
242 /********************************************************************************************************************/
243 /********************************************************************************************************************/
244
245 template<typename UserType>
246 ScalarPushInputWB<UserType>::ScalarPushInputWB(Module* owner, const std::string& name, std::string unit,
247 const std::string& description, const std::unordered_set<std::string>& tags)
248 : ScalarAccessor<UserType>(
249 owner, name, {VariableDirection::consuming, true}, unit, UpdateMode::push, description, tags) {}
250
251 /********************************************************************************************************************/
252 /********************************************************************************************************************/
253
254 template<typename UserType>
255 ScalarOutputPushRB<UserType>::ScalarOutputPushRB(Module* owner, const std::string& name, std::string unit,
256 const std::string& description, const std::unordered_set<std::string>& tags)
257 : ScalarAccessor<UserType>(
258 owner, name, {VariableDirection::feeding, true}, unit, UpdateMode::push, description, tags) {}
259
260 /********************************************************************************************************************/
261 /********************************************************************************************************************/
262
263 template<typename UserType>
265 std::string unit, const std::string& description, const std::unordered_set<std::string>& tags)
266 : ScalarAccessor<UserType>(
267 owner, name, {VariableDirection::feeding, true}, unit, UpdateMode::push, description, tags) {
268 this->addTag(ChimeraTK::SystemTags::reverseRecovery);
269 }
270
271 /********************************************************************************************************************/
272
273} /* namespace ChimeraTK */
static void incrementDataLossCounter(const std::string &name)
Increment counter for how many write() operations have overwritten unread data.
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
Accessor for scalar variables (i.e.
bool write(ChimeraTK::VersionNumber versionNumber)=delete
bool writeDestructively(ChimeraTK::VersionNumber versionNumber)=delete
void writeIfDifferent(UserType newValue, VersionNumber versionNumber, DataValidity validity)=delete
ScalarAccessor(ScalarAccessor< UserType > &&other) noexcept
Move constructor.
ScalarAccessor< UserType > & operator=(ScalarAccessor< UserType > &&other) noexcept
Move assignment.
void writeIfDifferent(UserType newValue)
ScalarAccessor< UserType > & operator=(ScalarAccessor< UserType > &other)=delete
void setAndWrite(UserType newValue, VersionNumber versionNumber)=delete
ScalarAccessor()=default
Default constructor creates a dysfunctional accessor (to be assigned with a real accessor later)
ScalarAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit, UpdateMode mode, const std::string &description, const std::unordered_set< std::string > &tags={})
void replace(const ChimeraTK::NDRegisterAccessorAbstractor< UserType > &newAccessor)=delete
Convenience class for input scalar accessors with UpdateMode::push.
ScalarPushInput(Module *owner, const std::string &name, std::string unit, const std::string &description, const std::unordered_set< std::string > &tags={})
Convenience class for input scalar accessors with return channel ("write back") and UpdateMode::push.
ScalarPushInputWB(Module *owner, const std::string &name, std::string unit, const std::string &description, const std::unordered_set< std::string > &tags={})
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 scalar accessors (always UpdateMode::push)
Convenience class for output scalar accessors with return channel ("read back") (always UpdateMode::p...
ScalarOutputPushRB(Module *owner, const std::string &name, std::string unit, const std::string &description, const std::unordered_set< std::string > &tags={})
Convenience class for output scalar accessors with return channel ("read back") (always UpdateMode::p...
Convenience class for input scalar accessors with UpdateMode::poll.
ScalarPollInput(Module *owner, const std::string &name, std::string unit, const std::string &description, const std::unordered_set< std::string > &tags={})
Struct to define the direction of variables.
Definition Flags.h:13