ChimeraTK-ApplicationCore
04.01.00
|
Implements access to a ChimeraTK::Device. More...
#include <DeviceManager.h>
Public Member Functions | |
DeviceManager (Application *application, const std::string &deviceAliasOrCDD) | |
Create DeviceManager which handles device exceptions and performs the recovery. More... | |
DeviceManager (DeviceManager &&other)=delete | |
DeviceManager & | operator= (DeviceManager &&other)=delete |
void | reportException (std::string errMsg) |
Use this function to report an exception. More... | |
void | prepare () override |
Prepare the execution of the module. More... | |
void | mainLoop () override |
This functions tries to open the device and set the deviceError. More... | |
DataValidity | getDataValidity () const override |
Return the data validity flag. More... | |
void | incrementDataFaultCounter () override |
Set the data validity flag to fault and increment the fault counter. More... | |
void | decrementDataFaultCounter () override |
Decrement the fault counter and set the data validity flag to ok if the counter has reached 0. More... | |
void | addInitialisationHandler (std::function< void(ChimeraTK::Device &)> initialisationHandler) |
Add initialisation handlers to the device. More... | |
void | addRecoveryAccessor (boost::shared_ptr< RecoveryHelper > recoveryAccessor) |
Add a TransferElement to the list DeviceModule::writeRecoveryOpen. More... | |
uint64_t | writeOrder () |
Each call to this function gives a unique number. More... | |
boost::shared_lock< boost::shared_mutex > | getRecoverySharedLock () |
Returns a shared lock for the DeviceModule::recoveryMutex. More... | |
void | waitForInitialValues () |
Wait for initial values coming from the device. More... | |
std::list< EntityOwner * > | getInputModulesRecursively (std::list< EntityOwner * > startList) override |
Use pointer to the module as unique identifier. More... | |
size_t | getCircularNetworkHash () const override |
Get the ID of the circular dependency network (0 if none). More... | |
const std::string & | getDeviceAliasOrURI () const |
Return associated device alias resp. More... | |
std::vector< VariableNetworkNode > | getNodesList () const |
Create and return list of VariableNetworkNodes for all device registers. More... | |
Device & | getDevice () |
Return the underlying ChimeraTK::Device object. More... | |
void | terminate () override |
Terminate the module. More... | |
Public Member Functions inherited from ChimeraTK::ApplicationModule | |
ApplicationModule (ModuleGroup *owner, const std::string &name, const std::string &description, const std::unordered_set< std::string > &tags={}) | |
Create ApplicationModule and register it with its owner. More... | |
ApplicationModule ()=default | |
Default constructor: Allows late initialisation of modules (e.g. More... | |
ApplicationModule (ApplicationModule &&other) noexcept | |
Move operation with the move constructor. More... | |
ApplicationModule & | operator= (ApplicationModule &&other) noexcept |
Move assignment. More... | |
~ApplicationModule () override | |
Destructor. More... | |
void | run () override |
Execute the module. More... | |
ModuleType | getModuleType () const override |
Return the module type of this module, or in case of a VirtualModule the module type this VirtualModule was derived from. More... | |
VersionNumber | getCurrentVersionNumber () const override |
Return the current version number which has been received with the last push-type read operation. More... | |
size_t | getDataFaultCounter () const |
Get the Number of inputs which report DataValidity::faulty. More... | |
void | setCurrentVersionNumber (VersionNumber versionNumber) override |
Set the current version number. More... | |
void | setCircularNetworkHash (size_t circularNetworkHash) |
Set the ID of the circular dependency network. More... | |
ChimeraTK::Model::ApplicationModuleProxy | getModel () |
Return the application model proxy representing this module. More... | |
void | unregisterModule (Module *module) override |
Unregister another module as a sub-module. More... | |
Logger::StreamProxy | logger (Logger::Severity severity) |
Convenicene function to obtain a logger stream with the given Severity. More... | |
Public Member Functions inherited from ChimeraTK::VariableGroup | |
VariableGroup (VariableGroup *owner, const std::string &name, const std::string &description, const std::unordered_set< std::string > &tags={}) | |
Constructor: Create VariableGroup register it with its owner. More... | |
VariableGroup ()=default | |
Default constructor: Allows late initialisation of VariableGroups (e.g. More... | |
VariableGroup (VariableGroup &&other) noexcept | |
Move constructor. More... | |
VariableGroup (const VariableGroup &other) noexcept=delete | |
VariableGroup & | operator= (VariableGroup &&other) noexcept |
Move assignment. More... | |
VariableGroup & | operator= (const VariableGroup &other) noexcept=delete |
ModuleType | getModuleType () const override |
Return the module type of this module, or in case of a VirtualModule the module type this VirtualModule was derived from. More... | |
ChimeraTK::Model::VariableGroupProxy | getModel () |
Return the application model proxy representing this module. More... | |
std::string | getVirtualQualifiedName () const override |
void | unregisterModule (Module *module) override |
Unregister another module as a sub-module. More... | |
Public Member Functions inherited from ChimeraTK::Module | |
Module (EntityOwner *owner, const std::string &name, const std::string &description, const std::unordered_set< std::string > &tags={}) | |
Constructor: Create Module by the given name with the given description and register it with its owner. More... | |
Module ()=default | |
Default constructor: Allows late initialisation of modules (e.g. More... | |
~Module () override | |
Destructor. More... | |
Module (Module &&other) noexcept | |
Move constructor. More... | |
Module & | operator= (Module &&other) noexcept |
Move assignment operator. More... | |
ChimeraTK::ReadAnyGroup | readAnyGroup () |
Create a ChimeraTK::ReadAnyGroup for all readable variables in this Module. More... | |
void | readAll (bool includeReturnChannels=false) |
Read all readable variables in the group. More... | |
void | readAllNonBlocking (bool includeReturnChannels=false) |
Just call readNonBlocking() on all readable variables in the group. More... | |
void | readAllLatest (bool includeReturnChannels=false) |
Just call readLatest() on all readable variables in the group. More... | |
void | writeAll (bool includeReturnChannels=false) |
Just call write() on all writable variables in the group. More... | |
void | writeAllDestructively (bool includeReturnChannels=false) |
Just call writeDestructively() on all writable variables in the group. More... | |
std::string | getQualifiedName () const override |
Get the fully qualified name of the module instance, i.e. More... | |
std::string | getFullDescription () const override |
Obtain the full description including the full description of the owner. More... | |
void | setOwner (EntityOwner *newOwner) |
Set a new owner. More... | |
EntityOwner * | getOwner () const |
VersionNumber | getCurrentVersionNumber () const override |
Return the current version number which has been received with the last push-type read operation. More... | |
void | setCurrentVersionNumber (VersionNumber version) override |
Set the current version number. More... | |
DataValidity | getDataValidity () const override |
Return the data validity flag. More... | |
void | incrementDataFaultCounter () override |
Set the data validity flag to fault and increment the fault counter. More... | |
void | decrementDataFaultCounter () override |
Decrement the fault counter and set the data validity flag to ok if the counter has reached 0. More... | |
std::list< EntityOwner * > | getInputModulesRecursively (std::list< EntityOwner * > startList) override |
Use pointer to the module as unique identifier. More... | |
size_t | getCircularNetworkHash () const override |
Get the ID of the circular dependency network (0 if none). More... | |
Module * | findApplicationModule () |
Find ApplicationModule owner. More... | |
void | disable () |
Disable the module such that it is not part of the Application. More... | |
Public Member Functions inherited from ChimeraTK::EntityOwner | |
EntityOwner (std::string name, std::string description, std::unordered_set< std::string > tags={}) | |
Constructor: Create EntityOwner by the given name with the given description. More... | |
EntityOwner () | |
Default constructor just for late initialisation. More... | |
virtual | ~EntityOwner ()=default |
Virtual destructor to make the type polymorphic. More... | |
EntityOwner (EntityOwner &&other) noexcept | |
Move constructor. More... | |
EntityOwner (const EntityOwner &other)=delete | |
EntityOwner & | operator= (EntityOwner &&other) noexcept |
Move assignment operator. More... | |
EntityOwner & | operator= (const EntityOwner &other)=delete |
const std::string & | getName () const |
Get the name of the module instance. More... | |
std::string | getQualifiedNameWithType () const |
Get the fully qualified name of the module instance, followed by the C++ data type (in pointy brackets) More... | |
const std::string & | getDescription () const |
Get the description of the module instance. More... | |
std::list< VariableNetworkNode > | getAccessorList () const |
Obtain the list of accessors/variables directly associated with this instance. More... | |
std::list< Module * > | getSubmoduleList () const |
Obtain the list of submodules associated with this instance. More... | |
std::list< VariableNetworkNode > | getAccessorListRecursive () const |
Obtain the list of accessors/variables associated with this instance and any submodules. More... | |
std::list< Module * > | getSubmoduleListRecursive () const |
Obtain the list of submodules associated with this instance and any submodules. More... | |
void | registerAccessor (VariableNetworkNode accessor) |
Called inside the constructor of Accessor: adds the accessor to the list. More... | |
void | unregisterAccessor (const VariableNetworkNode &accessor) |
Called inside the destructor of Accessor: removes the accessor from the list. More... | |
void | registerModule (Module *module, bool addTags=true) |
Register another module as a sub-module. More... | |
void | addTag (const std::string &tag) |
Add a tag to all Application-type nodes inside this group. More... | |
void | dump (const std::string &prefix="", std::ostream &stream=std::cout) const |
Print the full hierarchy to given stream. More... | |
bool | hasReachedTestableMode () |
Check whether this module has declared that it reached the testable mode. More... | |
template<typename T > | |
std::string | constant (T value) |
Create a variable name which will be automatically connected with a constant value. More... | |
Public Attributes | |
VoidOutput | deviceBecameFunctional {this, "deviceBecameFunctional", ""} |
A trigger that indicated that the device just became available again an error (in contrast to the error status which is also send when the device goes away). More... | |
Protected Member Functions | |
VersionNumber | getExceptionVersionNumber () |
Use this function to read the exception version number. More... | |
Protected Member Functions inherited from ChimeraTK::ApplicationModule | |
void | mainLoopWrapper () |
Wrapper around mainLoop(), to execute additional tasks in the thread before entering the main loop. More... | |
std::string | className () |
Name of the module class, used for logging and debugging purposes. More... | |
Protected Attributes | |
Device | _device |
std::string | _deviceAliasOrCDD |
Application * | _owner {nullptr} |
StatusWithMessage | _deviceError {this, "status", "Error status of the device"} |
A VariableGroup for exception status and message. More... | |
cppext::future_queue< std::string > | _errorQueue {5} |
Queue used for communication between reportException() and the moduleThread. More... | |
boost::shared_mutex | _errorMutex |
Mutex to protect deviceHasError. More... | |
VersionNumber | _exceptionVersionNumber = {} |
Version number of the last exception. More... | |
bool | _deviceHasError {true} |
The error flag whether the device is functional. More... | |
std::list< boost::shared_ptr< RecoveryHelper > > | _recoveryHelpers |
List of TransferElements to be written after the device has been recovered. More... | |
std::list< std::function< void(ChimeraTK::Device &)> > | _initialisationHandlers |
boost::shared_mutex | _recoveryMutex |
Mutex for writing the DeviceModule::writeRecoveryOpen. More... | |
bool | _isHoldingInitialValueLatch {true} |
Latch to halt accessors until initial values can be received. More... | |
boost::latch | _initialValueLatch {1} |
std::atomic< int64_t > | _synchronousTransferCounter {0} |
std::atomic< uint64_t > | _writeOrderCounter {0} |
std::list< RegisterPath > | _writeRegisterPaths |
std::list< RegisterPath > | _readRegisterPaths |
Protected Attributes inherited from ChimeraTK::ApplicationModule | |
boost::thread | _moduleThread |
The thread executing mainLoop() More... | |
VersionNumber | _currentVersionNumber {nullptr} |
Version number of last push-type read operation - will be passed on to any write operations. More... | |
std::atomic< size_t > | _dataFaultCounter {0} |
Number of inputs which report DataValidity::faulty. More... | |
size_t | _circularNetworkHash {0} |
Unique ID for the circular dependency network. More... | |
detail::CircularDependencyDetectionRecursionStopper | _recursionStopper |
Helper needed to stop the recursion when detecting circular dependency networks. More... | |
ChimeraTK::Model::ApplicationModuleProxy | _model |
Protected Attributes inherited from ChimeraTK::VariableGroup | |
ChimeraTK::Model::VariableGroupProxy | _model |
Protected Attributes inherited from ChimeraTK::Module | |
EntityOwner * | _owner {nullptr} |
Owner of this instance. More... | |
Protected Attributes inherited from ChimeraTK::EntityOwner | |
std::string | _name |
The name of this instance. More... | |
std::string | _description |
The description of this instance. More... | |
std::list< VariableNetworkNode > | _accessorList |
List of accessors owned by this instance. More... | |
std::list< Module * > | _moduleList |
List of modules owned by this instance. More... | |
std::unordered_set< std::string > | _tags |
List of tags to be added to all accessors and modules inside this module. More... | |
std::atomic< bool > | _testableModeReached {false} |
Flag used by the testable mode to identify whether a thread within the EntityOwner has reached the point where the testable mode lock is acquired. More... | |
Friends | |
struct | detail::CircularDependencyDetector |
template<typename UserType > | |
class | ExceptionHandlingDecorator |
Additional Inherited Members | |
Public Types inherited from ChimeraTK::EntityOwner | |
enum | ModuleType { ModuleType::ApplicationModule, ModuleType::ModuleGroup, ModuleType::VariableGroup, ModuleType::ControlSystem, ModuleType::Device, ModuleType::Invalid } |
Static Public Member Functions inherited from ChimeraTK::Module | |
static ConfigReader & | appConfig () |
Obtain the ConfigReader instance of the application. More... | |
Static Public Attributes inherited from ChimeraTK::EntityOwner | |
static constexpr std::string_view | namePrefixConstant {"/@CONST@"} |
Prefix for constants created by constant(). More... | |
Implements access to a ChimeraTK::Device.
Definition at line 20 of file DeviceManager.h.
ChimeraTK::DeviceManager::DeviceManager | ( | Application * | application, |
const std::string & | deviceAliasOrCDD | ||
) |
Create DeviceManager which handles device exceptions and performs the recovery.
Definition at line 12 of file DeviceManager.cc.
|
delete |
void ChimeraTK::DeviceManager::addInitialisationHandler | ( | std::function< void(ChimeraTK::Device &)> | initialisationHandler | ) |
Add initialisation handlers to the device.
Initialisation handlers are called after the device has been opened, or after the device is recovering from an error (i.e. an accessor has thrown an exception and Device::isFunctional() returns true afterwards).
You can add multiple handlers. They are executed in the sequence in which they are registered. If a handler has been registered in the constructor, it is called first.
The handler function is called from the DeviceManager thread (not from the thread with the accessor that threw the exception). It is handed a pointer to the instance of the DeviceManager where the handler was registered. The handler function may throw a ChimeraTK::runtime_error, so you don't have to catch errors thrown when accessing the Device inside the handler. After a handler has thrown an exception, the following handlers are not called. The DeviceModule will wait until the Device reports isFunctional() again and retry. The exception is reported to other modules and the control system.
Notice: Especially in network based devices which do not hold a permanent connection, it is not always possible to predict whether the next read()/write() will succeed. In this case the Device will always report isFunctional() and one just has to retry. In this case the DeviceModule will start the initialisation sequence every 500 ms.
Definition at line 297 of file DeviceManager.cc.
void ChimeraTK::DeviceManager::addRecoveryAccessor | ( | boost::shared_ptr< RecoveryHelper > | recoveryAccessor | ) |
Add a TransferElement to the list DeviceModule::writeRecoveryOpen.
This list will be written during a recovery, after the constant accessors DeviceModule::writeAfterOpen are written. This is locked by a unique_lock. You can get a shared_lock with getRecoverySharedLock().
Definition at line 303 of file DeviceManager.cc.
|
overridevirtual |
Decrement the fault counter and set the data validity flag to ok if the counter has reached 0.
This function will be called by all input accessors when receiving the an ok update if the previous update was faulty. The caller of this function must ensure that calles to this function are paired to a previous call to incrementDataFaultCounter().
Reimplemented from ChimeraTK::ApplicationModule.
Definition at line 354 of file DeviceManager.cc.
|
overridevirtual |
Get the ID of the circular dependency network (0 if none).
This information is only available after the Application has finalised all connections.
Reimplemented from ChimeraTK::ApplicationModule.
Definition at line 341 of file DeviceManager.cc.
|
inlineoverridevirtual |
Return the data validity flag.
If any This function will be called by all output accessors in their write functions.
Reimplemented from ChimeraTK::ApplicationModule.
Definition at line 46 of file DeviceManager.h.
|
inline |
Return the underlying ChimeraTK::Device object.
Definition at line 129 of file DeviceManager.h.
|
inline |
|
protected |
Use this function to read the exception version number.
It is locking the variable mutex correctly for you.
Definition at line 91 of file DeviceManager.cc.
|
overridevirtual |
Use pointer to the module as unique identifier.
Reimplemented from ChimeraTK::ApplicationModule.
Definition at line 327 of file DeviceManager.cc.
std::vector< VariableNetworkNode > ChimeraTK::DeviceManager::getNodesList | ( | ) | const |
Create and return list of VariableNetworkNodes for all device registers.
Definition at line 18 of file DeviceManager.cc.
boost::shared_lock< boost::shared_mutex > ChimeraTK::DeviceManager::getRecoverySharedLock | ( | ) |
Returns a shared lock for the DeviceModule::recoveryMutex.
This locks writing the list DeviceModule::writeRecoveryOpen, during a recovery.
Definition at line 315 of file DeviceManager.cc.
|
overridevirtual |
Set the data validity flag to fault and increment the fault counter.
This function will be called by all input accessors when receiving the a faulty update if the previous update was ok. The caller of this function must ensure that calls to this function are paired to a subsequent call to decrementDataFaultCounter().
Reimplemented from ChimeraTK::ApplicationModule.
Definition at line 347 of file DeviceManager.cc.
|
overridevirtual |
This functions tries to open the device and set the deviceError.
Once done it notifies the waiting thread(s). The function is running an endless loop inside its own thread (moduleThread).
Implements ChimeraTK::ApplicationModule.
Definition at line 98 of file DeviceManager.cc.
|
delete |
|
overridevirtual |
Prepare the execution of the module.
This function is called before any module is started (including internal modules like FanOuts) and before the initial values of the variables are pushed into the queues. Reading and writing variables at this point may result in undefined behaviour.
Reimplemented from ChimeraTK::Module.
Definition at line 282 of file DeviceManager.cc.
void ChimeraTK::DeviceManager::reportException | ( | std::string | errMsg | ) |
Use this function to report an exception.
It should be called whenever a ChimeraTK::runtime_error has been caught when trying to interact with this device. It is primarily used by the ExceptionHandlingDecorator, but also user modules can report exception and trigger the recovery mechanism like this.
Definition at line 61 of file DeviceManager.cc.
|
overridevirtual |
Terminate the module.
Must/will be called before destruction, if run() was called previously.
Reimplemented from ChimeraTK::ApplicationModule.
Definition at line 361 of file DeviceManager.cc.
void ChimeraTK::DeviceManager::waitForInitialValues | ( | ) |
Wait for initial values coming from the device.
This function will block until the device is opened and initialised, and initial values can be read from it.
Definition at line 321 of file DeviceManager.cc.
uint64_t ChimeraTK::DeviceManager::writeOrder | ( | ) |
Each call to this function gives a unique number.
It is atomically increased with each call. The smallest valid write order is 1.
Definition at line 309 of file DeviceManager.cc.
|
friend |
Definition at line 196 of file DeviceManager.h.
|
friend |
Definition at line 199 of file DeviceManager.h.
|
protected |
Definition at line 139 of file DeviceManager.h.
|
protected |
Definition at line 141 of file DeviceManager.h.
|
protected |
A VariableGroup for exception status and message.
It can be protected, as it is automatically connected to the control system in DeviceModule::defineConnections()
Definition at line 149 of file DeviceManager.h.
|
protected |
The error flag whether the device is functional.
protected by the errorMutex.
Definition at line 169 of file DeviceManager.h.
|
protected |
Mutex to protect deviceHasError.
Attention: In testable mode this mutex must only be locked when holding the testable mode mutex!
Definition at line 160 of file DeviceManager.h.
|
protected |
Queue used for communication between reportException() and the moduleThread.
Definition at line 154 of file DeviceManager.h.
|
protected |
Version number of the last exception.
Only access under the error mutex. Intentionally not initialised with nullptr. It is propagated as long as the device is not successfully opened.
Definition at line 166 of file DeviceManager.h.
|
protected |
Definition at line 178 of file DeviceManager.h.
|
protected |
Definition at line 188 of file DeviceManager.h.
|
protected |
Latch to halt accessors until initial values can be received.
Must be a latch and not a mutex as it is locked in a different thread than unlocked.
Definition at line 187 of file DeviceManager.h.
|
protected |
Definition at line 143 of file DeviceManager.h.
|
protected |
Definition at line 194 of file DeviceManager.h.
|
protected |
List of TransferElements to be written after the device has been recovered.
See function addRecoveryAccessor() for details.
Definition at line 175 of file DeviceManager.h.
|
protected |
Mutex for writing the DeviceModule::writeRecoveryOpen.
Definition at line 181 of file DeviceManager.h.
|
protected |
Definition at line 190 of file DeviceManager.h.
|
protected |
Definition at line 191 of file DeviceManager.h.
|
protected |
Definition at line 193 of file DeviceManager.h.
VoidOutput ChimeraTK::DeviceManager::deviceBecameFunctional {this, "deviceBecameFunctional", ""} |
A trigger that indicated that the device just became available again an error (in contrast to the error status which is also send when the device goes away).
The output is public so your module can connect to it and trigger re-sending of variables that have to be send to the device again. e.g. after this has re-booted. Attention: It is not send the first time the device is being opened. In this case the normal startup mechanism takes care that the data is send. Like the deviceError, it is automatically published to the control systen to ensure that there is at least one consumer connected.
Definition at line 85 of file DeviceManager.h.