ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
ExceptionDummyBackend.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 "DummyBackend.h"
7
8#include <utility>
9
10namespace ChimeraTK {
11
12 template<typename UserType>
13 struct ExceptionDummyPushDecorator;
14
15 struct ExceptionDummyPushDecoratorBase;
16
17 struct ExceptionDummyPollDecoratorBase;
18 template<typename UserType>
19 struct ExceptionDummyPollDecorator;
20
21 /********************************************************************************************************************/
22
24 public:
25 explicit ExceptionDummy(std::string const& mapFileName, const std::string& dataConsistencyKeyDescriptor = "");
26
28 boost::shared_ptr<NDRegisterAccessor<T>>(const RegisterPath&, size_t, size_t, AccessModeFlags));
29
30 static boost::shared_ptr<DeviceBackend> createInstance(
31 std::string address, std::map<std::string, std::string> parameters);
32
33 void open() override;
34
35 void closeImpl() override;
36
37 void read(uint64_t bar, uint64_t address, int32_t* data, size_t sizeInBytes) override;
38
39 void write(uint64_t bar, uint64_t address, int32_t const* data, size_t sizeInBytes) override;
40
42 void triggerPush(RegisterPath path, VersionNumber v = {});
43
49 size_t getWriteOrder(const RegisterPath& path);
50
54 size_t getWriteCount(const RegisterPath& path);
55
56 void activateAsyncRead() noexcept override;
57
58 void setExceptionImpl() noexcept override;
59
61 bool asyncReadActivated();
62
72
76 std::map<RegisterPath, DataValidity> _registerValidities;
80 path.setAltSeparator(".");
81 std::unique_lock<std::mutex> lk(_registerValiditiesMutex);
82 _registerValidities[path] = val;
83 }
86 path.setAltSeparator(".");
87 std::unique_lock<std::mutex> lk(_registerValiditiesMutex);
88 // simply return default enum value 0 = DataValidity::ok unless path is explicity found in map
89 return _registerValidities[path];
90 }
91
93 std::map<std::pair<uint64_t, uint64_t>, std::atomic<size_t>> _writeOrderMap;
94
96 std::atomic<size_t> _writeOrderCounter{0};
97
99 std::map<std::pair<uint64_t, uint64_t>, std::atomic<size_t>> _writeCounterMap;
100
101 private:
103 template<typename UserType>
104 boost::shared_ptr<NDRegisterAccessor<UserType>> getRegisterAccessor_impl(
105 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags);
106 };
107
108 /********************************************************************************************************************/
109
112 virtual void trigger() = 0;
113 bool _isActive{false};
114 bool _hasException{false};
115 };
116
117 /********************************************************************************************************************/
118
119 template<typename UserType>
122 boost::shared_ptr<ExceptionDummy> backend)
123 : NDRegisterAccessorDecorator<UserType>(target), _backend(std::move(backend)) {
124 assert(_target->isReadable());
125
126 this->_accessModeFlags = _target->getAccessModeFlags();
128
129 _readQueue =
130 _myReadQueue.template then<void>([&](Buffer current) { this->_current = current; }, std::launch::deferred);
131
132 _path = _target->getName();
134 _path /= "PUSH_READ";
135 }
136
138 std::unique_lock<std::mutex> lk(_backend->_pushDecoratorsMutex);
139 try {
140 auto& list = _backend->_pushDecorators.at(_path);
141 for(auto it = list.begin(); it != list.end(); ++it) {
142 if(it->lock().get() == nullptr) { // weak_ptr is already not lockable any more
143 list.erase(it);
144 return;
145 }
146 }
147 }
148 catch(std::exception& e) {
149 // The exception that could show up here is coming from >_pushDecorators.at().
150 // It might be std::out_of_range if the _path is not in, or an exception from the string comparison inside of
151 // std::map::at(). Both should not be possible be due to the code logic. The code will run into an assertion in
152 // debug mode. Let's hope the what() string gives us valuable information.
153 std::cout << "~ExceptionDummyPushDecorator(): Unexpected exception: " << e.what() << std::endl;
154 }
155 std::cout << "~ExceptionDummyPushDecorator(): Could not unlist instance!" << std::endl;
156 assert(false);
157 }
158
159 void interrupt() override { this->interrupt_impl(this->_myReadQueue); }
160
161 void setExceptionBackend(boost::shared_ptr<DeviceBackend> exceptionBackend) override {
162 // do not set it for the target, since we read from the target in trigger(), but that is the wrong place to
163 // call setException(). So we don't call it on our base class NDRegisterAccessorDecorator but on the
164 // TransferElement itself.
165 // Turn off the linter warning. This is intentional.
166 // NOLINTNEXTLINE(bugprone-parent-virtual-call)
167 TransferElement::setExceptionBackend(exceptionBackend);
168 }
169
170 struct Buffer {
171 std::vector<std::vector<UserType>> _data;
174 };
176
177 cppext::future_queue<Buffer> _myReadQueue{3};
178
179 void trigger() override {
180 try {
181 _hasException = false;
182 _target->read();
183 Buffer b;
184 b._data = _target->accessChannels();
185 b._version = _backend->_pushVersions[_path];
186 b._validity = _target->dataValidity();
187 _myReadQueue.push_overwrite(b);
188 }
189 // fixme: clang tidy says something else is escaping, don't know what
191 _isActive = false;
192 if(!_hasException) _myReadQueue.push_overwrite_exception(std::current_exception());
193 _hasException = true;
194 }
195 }
196
197 void doPreRead(TransferType) override {
198 // do not delegate read transfers to the target
199 if(!_backend->isOpen()) {
200 throw ChimeraTK::logic_error("Cannot read from closed device.");
201 }
202 }
203
204 void doPostRead(TransferType, bool updateDataBuffer) override {
205 // do not delegate read transfers to the target
206 if(updateDataBuffer) {
207 // do not update meta data if updateDataBuffer == false, since this is the equivalent to a backend
208 // implementation, not a decorator
212 }
213 }
214
215 boost::shared_ptr<ExceptionDummy> _backend;
217 using NDRegisterAccessorDecorator<UserType>::_target;
221 using NDRegisterAccessor<UserType>::buffer_2D;
222 };
223
224 /********************************************************************************************************************/
225
226 // non-template base class for UserType-agnostic insertion into std::map
230
232 template<typename UserType>
235 boost::shared_ptr<ExceptionDummy> backend)
236 : NDRegisterAccessorDecorator<UserType>(target), _backend(std::move(backend)) {
237 assert(_target->isReadable());
238
239 _path = _target->getName();
241 }
242
243 void doPostRead(TransferType type, bool updateDataBuffer) override {
245 // overwriting is only allowed for faulty.
247 }
248
249 boost::shared_ptr<ExceptionDummy> _backend;
251 using NDRegisterAccessorDecorator<UserType>::_target;
255 };
256
257 /********************************************************************************************************************/
258} // namespace ChimeraTK
Set of AccessMode flags with additional functionality for an easier handling.
Definition AccessMode.h:48
void add(AccessMode flag)
Add the given flag to the set.
Definition AccessMode.cc:62
Base class for DummyBackends, provides common functionality.
The dummy device opens a mapping file instead of a device, and implements all registers defined in th...
std::map< RegisterPath, DataValidity > _registerValidities
This map is used for setting individual (poll-type) variables to DataValidity=faulty.
std::map< std::pair< uint64_t, uint64_t >, std::atomic< size_t > > _writeOrderMap
Map used allow determining order of writes by tests. Map key is pair of bar and address.
std::map< RegisterPath, VersionNumber > _pushVersions
Map of version numbers to use in push decorators. Protected by _pushDecoratorMutex.
bool _activateNewPushAccessors
Flag is toggled by activateAsyncRead (true), setException (false) and close (false).
std::map< RegisterPath, std::list< boost::weak_ptr< ExceptionDummyPushDecoratorBase > > > _pushDecorators
Map of active ExceptionDummyPushDecorator. Protected by _pushDecoratorMutex.
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
void open() override
Open the device.
DEFINE_VIRTUAL_FUNCTION_OVERRIDE_VTABLE(DummyBackendBase, getRegisterAccessor_impl, boost::shared_ptr< NDRegisterAccessor< T > >(const RegisterPath &, size_t, size_t, AccessModeFlags))
std::mutex _registerValiditiesMutex
mutex to protect map _registerValidities
size_t getWriteOrder(const RegisterPath &path)
Function to obtain the write order number of a register.
DataValidity getValidity(RegisterPath path)
Query map for overwritten data validities.
std::map< std::pair< uint64_t, uint64_t >, std::atomic< size_t > > _writeCounterMap
Map used allow determining number of writes of a specific register by tests. Map key is pair of bar a...
void setValidity(RegisterPath path, DataValidity val)
Use decorator to overwrite returned data validity of individual (poll-type) variables.
void closeImpl() override
This closes the device, clears all internal registers, read-only settings and callback functions.
size_t getWriteCount(const RegisterPath &path)
Function to obtain the number of writes of a register since the creation of the backend.
std::mutex _pushDecoratorsMutex
Mutex to protect data structures for push decorators.
void setExceptionImpl() noexcept override
Function to be (optionally) implemented by backends if additional actions are needed when switching t...
void triggerPush(RegisterPath path, VersionNumber v={})
Function to trigger sending values for push-type variables.
std::atomic< size_t > _writeOrderCounter
Global counter for order numbers going into _writeOrderMap.
void activateAsyncRead() noexcept override
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
bool asyncReadActivated()
Function to test whether async read transfers are activated.
Base class for decorators of the NDRegisterAccessor.
N-dimensional register accessor.
std::vector< std::vector< UserType > > buffer_2D
Buffer of converted data elements.
Class to store a register path name.
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
virtual void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend)
Set the backend to which the exception has to be reported.
AccessModeFlags _accessModeFlags
The access mode flags for this transfer element.
DataValidity _dataValidity
The validity of the data in the application buffer.
void interrupt_impl(QUEUE_TYPE &dataTransportQueue)
Implementation of interrupt()
VersionNumber _versionNumber
The version number of the last successful transfer.
cppext::future_queue< void > _readQueue
The queue for asynchronous read transfers.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
Definition Exception.h:51
Exception thrown when a runtime error has occured.
Definition Exception.h:18
DataValidity
The current state of the data.
@ faulty
The data is considered valid.
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.
TransferType
Used to indicate the applicable operation on a Transferelement.
STL namespace.
A decorator that returns invalid data for polled variables.
ExceptionDummyPollDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< UserType > > &target, boost::shared_ptr< ExceptionDummy > backend)
DataValidity _dataValidity
The validity of the data in the application buffer.
boost::shared_ptr< ExceptionDummy > _backend
void doPostRead(TransferType type, bool updateDataBuffer) override
Backend specific implementation of postRead().
std::vector< std::vector< UserType > > _data
void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend) override
Set the backend to which the exception has to be reported.
DataValidity _dataValidity
The validity of the data in the application buffer.
VersionNumber _versionNumber
The version number of the last successful transfer.
cppext::future_queue< Buffer > _myReadQueue
cppext::future_queue< void > _readQueue
The queue for asynchronous read transfers.
ExceptionDummyPushDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< UserType > > &target, boost::shared_ptr< ExceptionDummy > backend)
void doPostRead(TransferType, bool updateDataBuffer) override
Backend specific implementation of postRead().
void interrupt() override
Return from a blocking read immediately and throw boost::thread_interrupted.
void doPreRead(TransferType) override
Backend specific implementation of preRead().
boost::shared_ptr< ExceptionDummy > _backend