12#include <ChimeraTK/SystemTags.h>
13#include <ChimeraTK/Utilities.h>
23 const std::unordered_set<std::string>& tags)
26 throw ChimeraTK::logic_error(
"ApplicationModule owner cannot be nullptr");
39 assert(!_moduleThread.joinable());
49 model.informMove(*
this);
70 while(!
_moduleThread.try_join_for(boost::chrono::milliseconds(10))) {
73 auto el{var.getAppAccessorNoType().getHighLevelImplElement()};
109 bool useSharedTestLockForStartup = (
dynamic_cast<DeviceManager*
>(
this) !=
nullptr);
119 for(
auto& variable : accList) {
124 assert(!variable.getAppAccessorNoType().getHighLevelImplElement()->getAccessModeFlags().has(
125 AccessMode::wait_for_new_data));
128 variable.getAppAccessorNoType().read();
135 "Initial value read for poll-type " + variable.getName(), useSharedTestLockForStartup);
140 for(
auto& variable : accList) {
144 variable.getDirection().withReturn && variable.getTags().contains(ChimeraTK::SystemTags::reverseRecovery);
155 "Initial value read for push-type " + variable.getName(), useSharedTestLockForStartup);
156 variable.getAppAccessorNoType().read();
160 "Initial value read for push-type " + variable.getName(), useSharedTestLockForStartup);
165 if(!useSharedTestLockForStartup) {
198 if(std::count(startList.begin(), startList.end(),
this)) {
212 startList.push_back(
this);
213 std::list<EntityOwner*> returnList{
222 auto proxy = accessor.getModel().visit(Model::returnApplicationModule, Model::keepApplicationModules,
224 if(!proxy.isValid()) {
227 auto& feedingModule = proxy.getApplicationModule();
229 auto thisInputsRecursiveModuleList = feedingModule.getInputModulesRecursively(startList);
231 assert(startList.size() <= thisInputsRecursiveModuleList.size());
232 auto copyStartIter = thisInputsRecursiveModuleList.begin();
233 std::advance(copyStartIter, startList.size());
235 returnList.insert(returnList.end(), copyStartIter, thisInputsRecursiveModuleList.end());
250 throw ChimeraTK::logic_error(
251 "Error: setCircularNetworkHash() called with different values for EntityOwner \"" +
_name +
"\" ");
254 throw ChimeraTK::logic_error(
"Error: setCircularNetworkHash() called after initialisation.");
263 return DataValidity::ok;
270 return DataValidity::ok;
274 return DataValidity::faulty;
detail::TestableMode & getTestableMode()
Get the TestableMode control object of this application.
static void registerThread(const std::string &name)
Register the thread in the application system and give it a name.
static Application & getInstance()
Obtain instance of the application.
detail::CircularDependencyDetector _circularDependencyDetector
boost::thread _moduleThread
The thread executing mainLoop()
DataValidity getDataValidity() const override
Return the data validity flag.
virtual void mainLoop()=0
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
VersionNumber _currentVersionNumber
Version number of last push-type read operation - will be passed on to any write operations.
void unregisterModule(Module *module) override
Unregister another module as a sub-module.
ChimeraTK::Model::ApplicationModuleProxy _model
void run() override
Execute the module.
detail::CircularDependencyDetectionRecursionStopper _recursionStopper
Helper needed to stop the recursion when detecting circular dependency networks.
std::string className()
Name of the module class, used for logging and debugging purposes.
ApplicationModule()=default
Default constructor: Allows late initialisation of modules (e.g.
void terminate() override
Terminate the module.
void decrementDataFaultCounter() override
Decrement the fault counter and set the data validity flag to ok if the counter has reached 0.
void setCircularNetworkHash(size_t circularNetworkHash)
Set the ID of the circular dependency network.
~ApplicationModule() override
Destructor.
void setCurrentVersionNumber(VersionNumber versionNumber) override
Set the current version number.
std::atomic< size_t > _dataFaultCounter
Number of inputs which report DataValidity::faulty.
std::list< EntityOwner * > getInputModulesRecursively(std::list< EntityOwner * > startList) override
Use pointer to the module as unique identifier.
size_t _circularNetworkHash
Unique ID for the circular dependency network.
void mainLoopWrapper()
Wrapper around mainLoop(), to execute additional tasks in the thread before entering the main loop.
size_t getCircularNetworkHash() const override
Get the ID of the circular dependency network (0 if none).
void incrementDataFaultCounter() override
Set the data validity flag to fault and increment the fault counter.
ApplicationModule & operator=(ApplicationModule &&other) noexcept
Move assignment.
Implements access to a ChimeraTK::Device.
std::string _name
The name of this instance.
std::atomic< bool > _testableModeReached
Flag used by the testable mode to identify whether a thread within the EntityOwner has reached the po...
std::list< VariableNetworkNode > getAccessorListRecursive() const
Obtain the list of accessors/variables associated with this instance and any submodules.
void remove(VariableGroup &module)
ModuleGroupProxy add(ModuleGroup &module)
bool isValid() const
Check if the model is valid.
ChimeraTK::Model::ModuleGroupProxy getModel()
Return the application model proxy representing this module.
Base class for ApplicationModule and DeviceModule, to have a common interface for these module types.
ChimeraTK::Model::VariableGroupProxy _model
VariableGroup & operator=(VariableGroup &&other) noexcept
Move assignment.
void unregisterModule(Module *module) override
Unregister another module as a sub-module.
constexpr ReturnFirstHitWithValue< void > returnFirstHit()
Stop the search after the first hit and return.
InvalidityTracer application module.
@ initialisation
Initialisation phase including ApplicationModule::prepare().