ChimeraTK-ApplicationCore 04.06.00
Loading...
Searching...
No Matches
DeviceManager.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 "ApplicationModule.h"
6#include "RecoveryHelper.h"
7#include "StatusWithMessage.h"
8#include "VoidAccessor.h"
9
10#include <ChimeraTK/Device.h>
11
12#include <boost/thread/latch.hpp>
13
14#include <barrier>
15#include <memory>
16
17namespace ChimeraTK {
18
19 /********************************************************************************************************************/
20
24 public:
28 DeviceManager(Application* application, const std::string& deviceAliasOrCDD);
29
30 // Move constructor/assignment is not used since DeviceManagers are stored as shared_ptr only.
31 DeviceManager(DeviceManager&& other) = delete;
33
39 void reportException(const std::string& errMsg);
40
41 void prepare() override;
42
47 void mainLoop() override;
48
53 void mainLoopImpl();
54
55 DataValidity getDataValidity() const override { return DataValidity::ok; }
56
57 void incrementDataFaultCounter() override;
58
59 void decrementDataFaultCounter() override;
60
82 void addInitialisationHandler(std::function<void(ChimeraTK::Device&)> initialisationHandler);
83
94 VoidOutput deviceBecameFunctional{this, "deviceBecameFunctional", ""};
95
101 void addRecoveryAccessor(boost::shared_ptr<RecoveryHelper> recoveryAccessor);
102
107 uint64_t writeOrder();
108
113 boost::shared_lock<boost::shared_mutex> getRecoverySharedLock();
114
120
121 std::list<EntityOwner*> getInputModulesRecursively(std::list<EntityOwner*> startList) override;
122
123 size_t getCircularNetworkHash() const override;
124
128 const std::string& getDeviceAliasOrURI() const { return _deviceAliasOrCDD; }
129
133 std::vector<VariableNetworkNode> getNodesList() const;
134
138 [[nodiscard]] Device& getDevice() { return _device; }
139
140 void terminate() override;
141
142 protected:
146 VersionNumber getExceptionVersionNumber();
147
149
150 std::string _deviceAliasOrCDD;
151
153
158 StatusWithMessage _deviceError{this, "status", "Error status of the device"};
159
163 cppext::future_queue<std::string> _errorQueue{5};
164
169 boost::shared_mutex _errorMutex;
170
176
178 bool _deviceHasError{true};
179
184 std::list<boost::shared_ptr<RecoveryHelper>> _recoveryHelpers;
185
186 /* The list of initialisation handler callback functions */
187 std::list<std::function<void(ChimeraTK::Device&)>> _initialisationHandlers;
188
190 boost::shared_mutex _recoveryMutex;
191
197 boost::latch _initialValueLatch{1};
198
199 std::atomic<int64_t> _synchronousTransferCounter{0};
200 std::atomic<uint64_t> _writeOrderCounter{0};
201
202 std::list<RegisterPath> _writeRegisterPaths;
203 std::list<RegisterPath> _readRegisterPaths;
204
206
207 template<typename UserType>
209
215 static constexpr const char* stageToString(RecoveryStage stage) {
216 switch(stage) {
218 return "RecoveryStage::NO_ERROR";
220 return "RecoveryStage::DETECTION";
222 return "RecoveryStage::OPEN";
224 return "RecoveryStage::INIT_HANDLERS";
226 return "RecoveryStage::RECOVERY_ACCESSORS";
228 return "RecoveryStage::CLEAR_ERROR";
229 }
230 throw ChimeraTK::logic_error("Unknown recovery stage, cannot convert to string.");
231 }
232
233 std::set<DeviceBackend::BackendID> recoveryBackendIDs;
234 Application* app{nullptr};
235
244 std::barrier<> recoveryBarrier{1};
245
250 std::atomic<RecoveryStage> errorAtStage{RecoveryStage::NO_ERROR};
251
253 std::atomic<bool> shutdown{false};
254
271 static std::mutex globalDeviceOpenMutex;
272
281
282 // Wait at the barrier for a stage to complete.
283 // Returns 'true' if the stage was completed successfully.
285
286 void setErrorAtStage(RecoveryStage stage);
287
288 // contains a barrier to wait that all threads have seen the change.
289 void resetErrorAtStage();
290 };
291 std::shared_ptr<RecoveryGroup> _recoveryGroup;
292
295 };
296
297 /********************************************************************************************************************/
298
299} // namespace ChimeraTK
Implements access to a ChimeraTK::Device.
uint64_t writeOrder()
Each call to this function gives a unique number.
std::atomic< int64_t > _synchronousTransferCounter
void decrementDataFaultCounter() override
Decrement the fault counter and set the data validity flag to ok if the counter has reached 0.
bool _deviceHasError
The error flag whether the device is functional.
size_t getCircularNetworkHash() const override
Get the ID of the circular dependency network (0 if none).
boost::latch _initialValueLatch
std::atomic< uint64_t > _writeOrderCounter
std::list< RegisterPath > _readRegisterPaths
std::vector< VariableNetworkNode > getNodesList() const
Create and return list of VariableNetworkNodes for all device registers.
void waitForInitialValues()
Wait for initial values coming from the device.
bool _isHoldingInitialValueLatch
Latch to halt accessors until initial values can be received.
const std::string & getDeviceAliasOrURI() const
Return associated device alias resp.
Device & getDevice()
Return the underlying ChimeraTK::Device object.
VersionNumber getExceptionVersionNumber()
Use this function to read the exception version number.
VersionNumber _exceptionVersionNumber
Version number of the last exception.
DataValidity getDataValidity() const override
Return the data validity flag.
void terminate() override
Terminate the module.
void addInitialisationHandler(std::function< void(ChimeraTK::Device &)> initialisationHandler)
Add initialisation handlers to the device.
std::list< RegisterPath > _writeRegisterPaths
boost::shared_mutex _errorMutex
Mutex to protect deviceHasError.
boost::shared_lock< boost::shared_mutex > getRecoverySharedLock()
Returns a shared lock for the DeviceModule::recoveryMutex.
DeviceManager(DeviceManager &&other)=delete
VoidOutput deviceBecameFunctional
A trigger that indicated that the device just became available again an error (in contrast to the err...
void reportException(const std::string &errMsg)
Use this function to report an exception.
std::shared_ptr< RecoveryGroup > _recoveryGroup
cppext::future_queue< std::string > _errorQueue
Queue used for communication between reportException() and the moduleThread.
void mainLoopImpl()
This functions tries to open the device and set the deviceError.
void addRecoveryAccessor(boost::shared_ptr< RecoveryHelper > recoveryAccessor)
Add a TransferElement to the list DeviceModule::writeRecoveryOpen.
std::list< std::function< void(ChimeraTK::Device &)> > _initialisationHandlers
DeviceManager & operator=(DeviceManager &&other)=delete
std::list< EntityOwner * > getInputModulesRecursively(std::list< EntityOwner * > startList) override
Use pointer to the module as unique identifier.
void prepare() override
Prepare the execution of the module.
boost::shared_mutex _recoveryMutex
Mutex for writing the DeviceModule::writeRecoveryOpen.
void mainLoop() override
Wrapper around the actual main loop implementation to add unsubscribing from the barrier to allow a c...
void incrementDataFaultCounter() override
Set the data validity flag to fault and increment the fault counter.
friend struct detail::CircularDependencyDetector
std::list< boost::shared_ptr< RecoveryHelper > > _recoveryHelpers
List of TransferElements to be written after the device has been recovered.
StatusWithMessage _deviceError
A VariableGroup for exception status and message.
std::string stageToString(RecoveryGroup::RecoveryStage stage)
Helper function for better error messages.
Decorator of the NDRegisterAccessor which facilitates tests of the application.
InvalidityTracer application module.
The shared state of a group of DeviceManagers which are recovering together.
static std::mutex globalDeviceOpenMutex
Protect the device open actions for all DeviceManagers and groups.
Application * app
Pointer to the application to access the recovery lock.
std::set< DeviceBackend::BackendID > recoveryBackendIDs
All backend ID in this recovery group.
static constexpr const char * stageToString(RecoveryStage stage)
bool waitForRecoveryStage(RecoveryStage stage)
std::atomic< bool > shutdown
Indicate that all DeviceManagers in the group should terminate their main loop.
std::mutex _initHandlerOpenCloseMutex
Protect closing and re-opening the device of any DeviceManager in a recovery group against each other...
void setErrorAtStage(RecoveryStage stage)
std::atomic< RecoveryStage > errorAtStage
Indicator whether recovery has to be repeated, and from which barrier.
std::barrier recoveryBarrier
A barrier is used to ensure that each stage of the recovery process is completed by all DeviceManager...
A VariableGroup for error status and message reporting.
Convenience class for output void (always UpdateMode::push)