ChimeraTK-ApplicationCore  04.01.00
Module.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 #include "Module.h"
4 
5 #include "Application.h"
6 #include "ApplicationModule.h"
7 #include "ConfigReader.h"
8 #include "DeviceModule.h"
9 #include "Utilities.h"
10 
11 namespace ChimeraTK {
12 
13  Module::Module(EntityOwner* owner, const std::string& name, const std::string& description,
14  const std::unordered_set<std::string>& tags)
15  : EntityOwner(ChimeraTK::Utilities::raiseIftrailingSlash(name, true), description, tags), _owner(owner) {
16  if(_owner != nullptr) {
17  _owner->registerModule(this);
18  }
19  }
20 
21  /********************************************************************************************************************/
22 
24  if(_owner != nullptr) {
25  _owner->unregisterModule(this);
26  }
27  }
28 
29  /********************************************************************************************************************/
30 
31  Module& Module::operator=(Module&& other) noexcept {
32  if(_owner != nullptr) {
33  _owner->unregisterModule(this);
34  }
35  if(other._owner != nullptr) {
36  other._owner->unregisterModule(&other);
37  }
38  _owner = other._owner;
39  other._owner = nullptr;
40  EntityOwner::operator=(std::move(other));
41  if(_owner != nullptr) {
42  _owner->registerModule(this, false);
43  }
44  return *this;
45  }
46  /********************************************************************************************************************/
47 
48  void Module::run() {
49  _testableModeReached = true; // Modules which don't implement run() have now reached testable mode
50  }
51 
52  /********************************************************************************************************************/
53 
54  ChimeraTK::ReadAnyGroup Module::readAnyGroup() {
55  auto recursiveAccessorList = getAccessorListRecursive();
56 
57  // put push-type transfer elements into a ReadAnyGroup
58  ChimeraTK::ReadAnyGroup group;
59  for(auto& accessor : recursiveAccessorList) {
60  if(accessor.getDirection() == VariableDirection{VariableDirection::feeding, false}) {
61  continue;
62  }
63  group.add(accessor.getAppAccessorNoType());
64  }
65 
66  group.finalise();
67  return group;
68  }
69 
70  /********************************************************************************************************************/
71 
72  void Module::readAll(bool includeReturnChannels) {
73  auto recursiveAccessorList = getAccessorListRecursive();
74  // first blockingly read all push-type variables
75  for(auto& accessor : recursiveAccessorList) {
76  if(accessor.getMode() != UpdateMode::push) {
77  continue;
78  }
79  if(includeReturnChannels) {
80  if(accessor.getDirection() == VariableDirection{VariableDirection::feeding, false}) {
81  continue;
82  }
83  }
84  else {
85  if(accessor.getDirection().dir != VariableDirection::consuming) {
86  continue;
87  }
88  }
89  accessor.getAppAccessorNoType().read();
90  }
91  // next non-blockingly read the latest values of all poll-type variables
92  for(auto& accessor : recursiveAccessorList) {
93  if(accessor.getMode() == UpdateMode::push) {
94  continue;
95  }
96  // poll-type accessors cannot have a readback channel
97  if(accessor.getDirection().dir != VariableDirection::consuming) {
98  continue;
99  }
100  accessor.getAppAccessorNoType().readLatest();
101  }
102  }
103 
104  /********************************************************************************************************************/
105 
106  void Module::readAllNonBlocking(bool includeReturnChannels) {
107  auto recursiveAccessorList = getAccessorListRecursive();
108  for(auto& accessor : recursiveAccessorList) {
109  if(accessor.getMode() != UpdateMode::push) {
110  continue;
111  }
112  if(includeReturnChannels) {
113  if(accessor.getDirection() == VariableDirection{VariableDirection::feeding, false}) {
114  continue;
115  }
116  }
117  else {
118  if(accessor.getDirection().dir != VariableDirection::consuming) {
119  continue;
120  }
121  }
122  accessor.getAppAccessorNoType().readNonBlocking();
123  }
124  for(auto& accessor : recursiveAccessorList) {
125  if(accessor.getMode() == UpdateMode::push) {
126  continue;
127  }
128  // poll-type accessors cannot have a readback channel
129  if(accessor.getDirection().dir != VariableDirection::consuming) {
130  continue;
131  }
132  accessor.getAppAccessorNoType().readLatest();
133  }
134  }
135 
136  /********************************************************************************************************************/
137 
138  void Module::readAllLatest(bool includeReturnChannels) {
139  auto recursiveAccessorList = getAccessorListRecursive();
140  for(auto& accessor : recursiveAccessorList) {
141  if(includeReturnChannels) {
142  if(accessor.getDirection() == VariableDirection{VariableDirection::feeding, false}) {
143  continue;
144  }
145  }
146  else {
147  if(accessor.getDirection().dir != VariableDirection::consuming) {
148  continue;
149  }
150  }
151  accessor.getAppAccessorNoType().readLatest();
152  }
153  }
154 
155  /********************************************************************************************************************/
156 
157  void Module::writeAll(bool includeReturnChannels) {
158  auto versionNumber = getCurrentVersionNumber();
159  auto recursiveAccessorList = getAccessorListRecursive();
160  for(auto& accessor : recursiveAccessorList) {
161  if(includeReturnChannels) {
162  if(accessor.getDirection() == VariableDirection{VariableDirection::consuming, false}) {
163  continue;
164  }
165  }
166  else {
167  if(accessor.getDirection().dir != VariableDirection::feeding) {
168  continue;
169  }
170  }
171  accessor.getAppAccessorNoType().write(versionNumber);
172  }
173  }
174 
175  /********************************************************************************************************************/
176 
177  void Module::writeAllDestructively(bool includeReturnChannels) {
178  auto versionNumber = getCurrentVersionNumber();
179  auto recursiveAccessorList = getAccessorListRecursive();
180  for(auto& accessor : recursiveAccessorList) {
181  if(includeReturnChannels) {
182  if(accessor.getDirection() == VariableDirection{VariableDirection::consuming, false}) {
183  continue;
184  }
185  }
186  else {
187  if(accessor.getDirection().dir != VariableDirection::feeding) {
188  continue;
189  }
190  }
191  accessor.getAppAccessorNoType().writeDestructively(versionNumber);
192  }
193  }
194 
195  /********************************************************************************************************************/
196 
199  auto* ret = dynamic_cast<ApplicationModule*>(this);
200  assert(ret != nullptr);
201  return ret;
202  }
204  auto* ret = dynamic_cast<DeviceModule*>(this);
205  assert(ret != nullptr);
206  return ret;
207  }
209  auto* owningModule = dynamic_cast<Module*>(getOwner());
210  assert(owningModule != nullptr);
211  return owningModule->findApplicationModule();
212  }
213  throw ChimeraTK::logic_error(
214  "EntityOwner::findApplicationModule() called on neither an ApplicationModule nor a VariableGroup.");
215  }
216 
217  /********************************************************************************************************************/
218 
219  std::string Module::getQualifiedName() const {
220  return ((_owner != nullptr) ? _owner->getQualifiedName() : "") + "/" + _name;
221  }
222 
223  /********************************************************************************************************************/
224 
225  std::string Module::getFullDescription() const {
226  if(_owner == nullptr) {
227  return _description;
228  }
229  auto ownerDescription = _owner->getFullDescription();
230  if(ownerDescription.empty()) {
231  return _description;
232  }
233  if(_description.empty()) {
234  return ownerDescription;
235  }
236  return ownerDescription + " - " + _description;
237  }
238 
239  /********************************************************************************************************************/
240 
241  std::list<EntityOwner*> Module::getInputModulesRecursively(std::list<EntityOwner*> startList) {
242  if(_owner == nullptr) {
243  return {};
244  }
245 
246  return _owner->getInputModulesRecursively(startList);
247  }
248 
249  /********************************************************************************************************************/
250 
253  }
254 
255  /********************************************************************************************************************/
256 
258  for(const auto& acc : getAccessorList()) {
259  auto m = acc.getModel();
260  if(m.isValid()) {
261  m.removeNode(acc);
262  }
263  }
264 
265  for(auto* submod : getSubmoduleList()) {
266  submod->disable();
267  }
268 
269  if(_owner) {
270  _owner->unregisterModule(this);
271  _owner = nullptr;
272  }
273  }
274 
275  /********************************************************************************************************************/
276 
277 } /* namespace ChimeraTK */
ChimeraTK::EntityOwner::getAccessorListRecursive
std::list< VariableNetworkNode > getAccessorListRecursive() const
Obtain the list of accessors/variables associated with this instance and any submodules.
Definition: EntityOwner.cc:69
ChimeraTK::Module::findApplicationModule
Module * findApplicationModule()
Find ApplicationModule owner.
Definition: Module.cc:197
ChimeraTK::VariableDirection
Struct to define the direction of variables.
Definition: Flags.h:13
ChimeraTK::ConfigReader
Generic module to read an XML config file and provide the defined values as constant variables.
Definition: ConfigReader.h:113
ChimeraTK::Module::appConfig
static ConfigReader & appConfig()
Obtain the ConfigReader instance of the application.
Definition: Module.cc:251
ChimeraTK::Module::run
virtual void run()
Execute the module.
Definition: Module.cc:48
ConfigReader.h
ChimeraTK::Module::getOwner
EntityOwner * getOwner() const
Definition: Module.h:96
ChimeraTK::EntityOwner::ModuleType::ApplicationModule
@ ApplicationModule
ChimeraTK::Module::~Module
~Module() override
Destructor.
Definition: Module.cc:23
ChimeraTK::Module::getFullDescription
std::string getFullDescription() const override
Obtain the full description including the full description of the owner.
Definition: Module.cc:225
Utilities.h
ChimeraTK::EntityOwner
Base class for owners of other EntityOwners (e.g.
Definition: EntityOwner.h:38
ChimeraTK::EntityOwner::ModuleType::VariableGroup
@ VariableGroup
ChimeraTK::Module::readAllNonBlocking
void readAllNonBlocking(bool includeReturnChannels=false)
Just call readNonBlocking() on all readable variables in the group.
Definition: Module.cc:106
ChimeraTK::DeviceModule
Definition: DeviceModule.h:20
ChimeraTK::VariableDirection::consuming
@ consuming
Definition: Flags.h:18
ChimeraTK::EntityOwner::getInputModulesRecursively
virtual std::list< EntityOwner * > getInputModulesRecursively(std::list< EntityOwner * > startList)=0
Use pointer to the module as unique identifier.
ChimeraTK::EntityOwner::_description
std::string _description
The description of this instance.
Definition: EntityOwner.h:174
ChimeraTK::EntityOwner::getSubmoduleList
std::list< Module * > getSubmoduleList() const
Obtain the list of submodules associated with this instance.
Definition: EntityOwner.h:80
ChimeraTK::EntityOwner::registerModule
void registerModule(Module *module, bool addTags=true)
Register another module as a sub-module.
Definition: EntityOwner.cc:52
ChimeraTK::Application::getInstance
static Application & getInstance()
Obtain instance of the application.
Definition: Application.cc:261
ChimeraTK::Application::getConfigReader
ConfigReader & getConfigReader()
Definition: Application.h:189
ChimeraTK::UpdateMode::push
@ push
ChimeraTK::ApplicationModule
Definition: ApplicationModule.h:24
DeviceModule.h
ChimeraTK::Module::readAnyGroup
ChimeraTK::ReadAnyGroup readAnyGroup()
Create a ChimeraTK::ReadAnyGroup for all readable variables in this Module.
Definition: Module.cc:54
ChimeraTK::Module::getInputModulesRecursively
std::list< EntityOwner * > getInputModulesRecursively(std::list< EntityOwner * > startList) override
Use pointer to the module as unique identifier.
Definition: Module.cc:241
ChimeraTK::Module::writeAllDestructively
void writeAllDestructively(bool includeReturnChannels=false)
Just call writeDestructively() on all writable variables in the group.
Definition: Module.cc:177
ChimeraTK::Utilities::raiseIftrailingSlash
std::string raiseIftrailingSlash(const std::string &name, bool isModule)
Raises logic error if name ends in a slash, or if it contains consecutive slashes.
Definition: Utilities.cc:116
ChimeraTK::VariableDirection::feeding
@ feeding
Definition: Flags.h:18
Application.h
ChimeraTK::EntityOwner::getAccessorList
std::list< VariableNetworkNode > getAccessorList() const
Obtain the list of accessors/variables directly associated with this instance.
Definition: EntityOwner.h:77
ChimeraTK::EntityOwner::getQualifiedName
virtual std::string getQualifiedName() const =0
Get the fully qualified name of the module instance, i.e.
ChimeraTK::Module::_owner
EntityOwner * _owner
Owner of this instance.
Definition: Module.h:139
ChimeraTK::Module::readAll
void readAll(bool includeReturnChannels=false)
Read all readable variables in the group.
Definition: Module.cc:72
ChimeraTK::Module::writeAll
void writeAll(bool includeReturnChannels=false)
Just call write() on all writable variables in the group.
Definition: Module.cc:157
ChimeraTK::EntityOwner::operator=
EntityOwner & operator=(EntityOwner &&other) noexcept
Move assignment operator.
Definition: EntityOwner.cc:28
ChimeraTK::Module::Module
Module()=default
Default constructor: Allows late initialisation of modules (e.g.
ChimeraTK::Module::getCurrentVersionNumber
VersionNumber getCurrentVersionNumber() const override
Return the current version number which has been received with the last push-type read operation.
Definition: Module.h:98
ChimeraTK::EntityOwner::ModuleType::Device
@ Device
ChimeraTK::Module::getQualifiedName
std::string getQualifiedName() const override
Get the fully qualified name of the module instance, i.e.
Definition: Module.cc:219
ApplicationModule.h
ChimeraTK::EntityOwner::getModuleType
virtual ModuleType getModuleType() const =0
Return the module type of this module, or in case of a VirtualModule the module type this VirtualModu...
ChimeraTK::EntityOwner::_name
std::string _name
The name of this instance.
Definition: EntityOwner.h:171
Module.h
ChimeraTK::Module::readAllLatest
void readAllLatest(bool includeReturnChannels=false)
Just call readLatest() on all readable variables in the group.
Definition: Module.cc:138
ChimeraTK::EntityOwner::unregisterModule
virtual void unregisterModule(Module *module)
Unregister another module as a sub-module.
Definition: EntityOwner.cc:63
ChimeraTK::Module::operator=
Module & operator=(Module &&other) noexcept
Move assignment operator.
Definition: Module.cc:31
ChimeraTK
InvalidityTracer application module.
Definition: spec_dataValidityPropagation.dox:2
ChimeraTK::EntityOwner::getFullDescription
virtual std::string getFullDescription() const =0
Obtain the full description including the full description of the owner.
ChimeraTK::Module::disable
void disable()
Disable the module such that it is not part of the Application.
Definition: Module.cc:257
ChimeraTK::EntityOwner::_testableModeReached
std::atomic< bool > _testableModeReached
Flag used by the testable mode to identify whether a thread within the EntityOwner has reached the po...
Definition: EntityOwner.h:190
ChimeraTK::Module
Base class for ApplicationModule and DeviceModule, to have a common interface for these module types.
Definition: Module.h:21