ChimeraTK-DeviceAccess  03.18.00
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 
10 namespace ChimeraTK {
11 
12  template<typename UserType>
14 
16 
18  template<typename UserType>
20 
21  /********************************************************************************************************************/
22 
24  public:
25  explicit ExceptionDummy(std::string const& mapFileName);
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 
66  std::map<RegisterPath, std::list<boost::weak_ptr<ExceptionDummyPushDecoratorBase>>> _pushDecorators;
68  std::map<RegisterPath, VersionNumber> _pushVersions;
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 
111  virtual ~ExceptionDummyPushDecoratorBase() = default;
112  virtual void trigger() = 0;
113  bool _isActive{false};
114  bool _hasException{false};
115  };
116 
117  /********************************************************************************************************************/
118 
119  template<typename UserType>
120  struct ExceptionDummyPushDecorator : NDRegisterAccessorDecorator<UserType>, ExceptionDummyPushDecoratorBase {
122  boost::shared_ptr<ExceptionDummy> backend)
123  : NDRegisterAccessorDecorator<UserType>(target), _backend(std::move(backend)) {
124  assert(_target->isReadable());
125 
126  this->_accessModeFlags = _target->getAccessModeFlags();
127  this->_accessModeFlags.add(AccessMode::wait_for_new_data);
128 
129  _readQueue =
130  _myReadQueue.template then<void>([&](Buffer current) { this->_current = current; }, std::launch::deferred);
131 
132  _path = _target->getName();
133  _path.setAltSeparator(".");
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
190  catch(ChimeraTK::runtime_error&) {
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
211  buffer_2D = _current._data;
212  }
213  }
214 
215  boost::shared_ptr<ExceptionDummy> _backend;
222  };
223 
224  /********************************************************************************************************************/
225 
226  // non-template base class for UserType-agnostic insertion into std::map
228  virtual ~ExceptionDummyPollDecoratorBase() = default;
229  };
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();
240  _path.setAltSeparator(".");
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;
255  };
256 
257  /********************************************************************************************************************/
258 } // namespace ChimeraTK
ChimeraTK::ExceptionDummy::getWriteCount
size_t getWriteCount(const RegisterPath &path)
Function to obtain the number of writes of a register since the creation of the backend.
Definition: ExceptionDummyBackend.cc:77
ChimeraTK::ExceptionDummy::_registerValidities
std::map< RegisterPath, DataValidity > _registerValidities
This map is used for setting individual (poll-type) variables to DataValidity=faulty.
Definition: ExceptionDummyBackend.h:76
ChimeraTK::ExceptionDummyPollDecorator::_backend
boost::shared_ptr< ExceptionDummy > _backend
Definition: ExceptionDummyBackend.h:249
ChimeraTK::ExceptionDummyPushDecorator::ExceptionDummyPushDecorator
ExceptionDummyPushDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< UserType >> &target, boost::shared_ptr< ExceptionDummy > backend)
Definition: ExceptionDummyBackend.h:121
ChimeraTK::ExceptionDummy
Definition: ExceptionDummyBackend.h:23
ChimeraTK::ExceptionDummyPushDecoratorBase
Definition: ExceptionDummyBackend.h:110
ChimeraTK::ExceptionDummyPollDecorator::_path
RegisterPath _path
Definition: ExceptionDummyBackend.h:250
ChimeraTK::DummyBackendBase
Base class for DummyBackends, provides common functionality.
Definition: DummyBackendBase.h:31
ChimeraTK::DataValidity::faulty
@ faulty
The data is considered valid.
ChimeraTK::ExceptionDummy::setExceptionImpl
void setExceptionImpl() noexcept override
Function to be (optionally) implemented by backends if additional actions are needed when switching t...
Definition: ExceptionDummyBackend.cc:46
ChimeraTK::ExceptionDummyPushDecorator::_versionNumber
VersionNumber _versionNumber
The version number of the last successful transfer.
Definition: TransferElement.h:851
DummyBackend.h
ChimeraTK::ExceptionDummyPushDecoratorBase::_isActive
bool _isActive
Definition: ExceptionDummyBackend.h:113
ChimeraTK::ExceptionDummy::createInstance
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
Definition: ExceptionDummyBackend.cc:98
ChimeraTK::ExceptionDummyPollDecorator::ExceptionDummyPollDecorator
ExceptionDummyPollDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< UserType >> &target, boost::shared_ptr< ExceptionDummy > backend)
Definition: ExceptionDummyBackend.h:234
ChimeraTK::ExceptionDummy::_writeOrderCounter
std::atomic< size_t > _writeOrderCounter
Global counter for order numbers going into _writeOrderMap.
Definition: ExceptionDummyBackend.h:96
ChimeraTK::ExceptionDummyPushDecorator::_dataValidity
DataValidity _dataValidity
The validity of the data in the application buffer.
Definition: TransferElement.h:855
ChimeraTK::ExceptionDummyPollDecoratorBase
Definition: ExceptionDummyBackend.h:227
ChimeraTK::ExceptionDummy::_pushDecoratorsMutex
std::mutex _pushDecoratorsMutex
Mutex to protect data structures for push decorators.
Definition: ExceptionDummyBackend.h:64
ChimeraTK::ExceptionDummy::activateAsyncRead
void activateAsyncRead() noexcept override
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
Definition: ExceptionDummyBackend.cc:25
ChimeraTK::ExceptionDummy::_writeCounterMap
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...
Definition: ExceptionDummyBackend.h:99
ChimeraTK::ExceptionDummyPushDecorator::_path
RegisterPath _path
Definition: ExceptionDummyBackend.h:216
ChimeraTK::ExceptionDummyPushDecorator::Buffer
Definition: ExceptionDummyBackend.h:170
ChimeraTK::RegisterPath::setAltSeparator
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
Definition: RegisterPath.h:37
ChimeraTK::ExceptionDummyPushDecorator::setExceptionBackend
void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend) override
Definition: ExceptionDummyBackend.h:161
ChimeraTK::ExceptionDummyPushDecorator::~ExceptionDummyPushDecorator
~ExceptionDummyPushDecorator() override
Definition: ExceptionDummyBackend.h:137
ChimeraTK::runtime_error
Exception thrown when a runtime error has occured.
Definition: Exception.h:18
NDRegisterAccessorDecorator.h
ChimeraTK::ExceptionDummy::getValidity
DataValidity getValidity(RegisterPath path)
Query map for overwritten data validities.
Definition: ExceptionDummyBackend.h:85
ChimeraTK::ExceptionDummy::_pushDecorators
std::map< RegisterPath, std::list< boost::weak_ptr< ExceptionDummyPushDecoratorBase > > > _pushDecorators
Map of active ExceptionDummyPushDecorator. Protected by _pushDecoratorMutex.
Definition: ExceptionDummyBackend.h:66
ChimeraTK::ExceptionDummyPushDecorator::doPreRead
void doPreRead(TransferType) override
Definition: ExceptionDummyBackend.h:197
ChimeraTK::ExceptionDummyPushDecorator::Buffer::_validity
DataValidity _validity
Definition: ExceptionDummyBackend.h:173
ChimeraTK::ExceptionDummyPushDecorator::_myReadQueue
cppext::future_queue< Buffer > _myReadQueue
Definition: ExceptionDummyBackend.h:177
ChimeraTK::ExceptionDummy::ExceptionDummy
ExceptionDummy(std::string const &mapFileName)
Definition: ExceptionDummyBackend.cc:92
ChimeraTK::ExceptionDummyPushDecorator::interrupt
void interrupt() override
Definition: ExceptionDummyBackend.h:159
ChimeraTK::DataValidity
DataValidity
The current state of the data.
Definition: TransferElement.h:41
ChimeraTK::ExceptionDummyPollDecorator::_dataValidity
DataValidity _dataValidity
The validity of the data in the application buffer.
Definition: TransferElement.h:855
ChimeraTK::ExceptionDummyPushDecorator
Definition: ExceptionDummyBackend.h:13
ChimeraTK::ExceptionDummyPushDecorator::doPostRead
void doPostRead(TransferType, bool updateDataBuffer) override
Definition: ExceptionDummyBackend.h:204
ChimeraTK::AccessMode::wait_for_new_data
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.
ChimeraTK::TransferElement::setExceptionBackend
virtual void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend)
Set the backend to which the exception has to be reported.
Definition: TransferElement.h:295
ChimeraTK::ExceptionDummy::read
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
Definition: ExceptionDummyBackend.cc:128
ChimeraTK::TransferElement::_dataValidity
DataValidity _dataValidity
The validity of the data in the application buffer.
Definition: TransferElement.h:855
ChimeraTK::ExceptionDummyPushDecorator::Buffer::_version
VersionNumber _version
Definition: ExceptionDummyBackend.h:172
ChimeraTK::ExceptionDummyPushDecorator::_current
Buffer _current
Definition: ExceptionDummyBackend.h:175
ChimeraTK::ExceptionDummy::_writeOrderMap
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.
Definition: ExceptionDummyBackend.h:93
ChimeraTK::ExceptionDummyPollDecorator
A decorator that returns invalid data for polled variables.
Definition: ExceptionDummyBackend.h:19
ChimeraTK::TransferType
TransferType
Used to indicate the applicable operation on a Transferelement.
Definition: TransferElement.h:51
ChimeraTK::ExceptionDummyPushDecoratorBase::_hasException
bool _hasException
Definition: ExceptionDummyBackend.h:114
ChimeraTK::ExceptionDummy::getWriteOrder
size_t getWriteOrder(const RegisterPath &path)
Function to obtain the write order number of a register.
Definition: ExceptionDummyBackend.cc:69
ChimeraTK::ExceptionDummy::open
void open() override
Open the device.
Definition: ExceptionDummyBackend.cc:110
ChimeraTK::ExceptionDummy::_activateNewPushAccessors
bool _activateNewPushAccessors
Flag is toggled by activateAsyncRead (true), setException (false) and close (false).
Definition: ExceptionDummyBackend.h:71
ChimeraTK::NDRegisterAccessorDecorator
Base class for decorators of the NDRegisterAccessor.
Definition: NDRegisterAccessorDecorator.h:120
ChimeraTK::ExceptionDummy::setValidity
void setValidity(RegisterPath path, DataValidity val)
Use decorator to overwrite returned data validity of individual (poll-type) variables.
Definition: ExceptionDummyBackend.h:79
ChimeraTK::ExceptionDummy::DEFINE_VIRTUAL_FUNCTION_OVERRIDE_VTABLE
DEFINE_VIRTUAL_FUNCTION_OVERRIDE_VTABLE(DummyBackendBase, getRegisterAccessor_impl, boost::shared_ptr< NDRegisterAccessor< T >>(const RegisterPath &, size_t, size_t, AccessModeFlags))
ChimeraTK::ExceptionDummyPushDecorator::Buffer::_data
std::vector< std::vector< UserType > > _data
Definition: ExceptionDummyBackend.h:171
ChimeraTK::ExceptionDummyPushDecoratorBase::trigger
virtual void trigger()=0
ChimeraTK::ExceptionDummyPushDecorator::trigger
void trigger() override
Definition: ExceptionDummyBackend.h:179
ChimeraTK::RegisterPath
Class to store a register path name.
Definition: RegisterPath.h:16
ChimeraTK::ExceptionDummyPushDecorator::_readQueue
cppext::future_queue< void > _readQueue
The queue for asynchronous read transfers.
Definition: TransferElement.h:847
ChimeraTK::ExceptionDummyPushDecorator::_backend
boost::shared_ptr< ExceptionDummy > _backend
Definition: ExceptionDummyBackend.h:215
ChimeraTK::ExceptionDummy::triggerPush
void triggerPush(RegisterPath path, VersionNumber v={})
Function to trigger sending values for push-type variables.
Definition: ExceptionDummyBackend.cc:10
ChimeraTK::ExceptionDummy::_registerValiditiesMutex
std::mutex _registerValiditiesMutex
mutex to protect map _registerValidities
Definition: ExceptionDummyBackend.h:74
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
ChimeraTK::ExceptionDummyPollDecoratorBase::~ExceptionDummyPollDecoratorBase
virtual ~ExceptionDummyPollDecoratorBase()=default
ChimeraTK::TransferElement::_readQueue
cppext::future_queue< void > _readQueue
The queue for asynchronous read transfers.
Definition: TransferElement.h:847
ChimeraTK::ExceptionDummy::asyncReadActivated
bool asyncReadActivated()
Function to test whether async read transfers are activated.
Definition: ExceptionDummyBackend.cc:85
ChimeraTK::DummyBackend
The dummy device opens a mapping file instead of a device, and implements all registers defined in th...
Definition: DummyBackend.h:45
ChimeraTK::ExceptionDummy::write
void write(uint64_t bar, uint64_t address, int32_t const *data, size_t sizeInBytes) override
Write function to be implemented by backends.
Definition: ExceptionDummyBackend.cc:138
ChimeraTK::AccessModeFlags
Set of AccessMode flags with additional functionality for an easier handling.
Definition: AccessMode.h:48
ChimeraTK::ExceptionDummyPushDecoratorBase::~ExceptionDummyPushDecoratorBase
virtual ~ExceptionDummyPushDecoratorBase()=default
ChimeraTK::ExceptionDummy::closeImpl
void closeImpl() override
This closes the device, clears all internal registers, read-only settings and callback functions.
Definition: ExceptionDummyBackend.cc:121
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::ExceptionDummy::_pushVersions
std::map< RegisterPath, VersionNumber > _pushVersions
Map of version numbers to use in push decorators. Protected by _pushDecoratorMutex.
Definition: ExceptionDummyBackend.h:68
ChimeraTK::NDRegisterAccessor< T >
ChimeraTK::ExceptionDummyPollDecorator::doPostRead
void doPostRead(TransferType type, bool updateDataBuffer) override
Definition: ExceptionDummyBackend.h:243
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51
ChimeraTK::TransferElement::_versionNumber
VersionNumber _versionNumber
The version number of the last successful transfer.
Definition: TransferElement.h:851