ChimeraTK-DeviceAccess  03.18.00
ExceptionDummyBackend.cc
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
4 
5 namespace ChimeraTK {
6 
7  /********************************************************************************************************************/
8 
11  path.setAltSeparator(".");
12  std::unique_lock<std::mutex> lk(_pushDecoratorsMutex);
13  _pushVersions[path] = v;
14  for(auto& acc_weak : _pushDecorators[path]) {
15  auto acc = acc_weak.lock();
16  if(!acc->_isActive) continue;
17  lk.unlock(); // next line might call setException()...
18  acc->trigger();
19  lk.lock();
20  }
21  }
22 
23  /********************************************************************************************************************/
24 
27 
28  std::unique_lock<std::mutex> lk(_pushDecoratorsMutex);
29  for(auto& pair : _pushDecorators) {
30  _pushVersions[pair.first] = {};
31  for(auto& acc_weak : pair.second) {
32  auto acc = acc_weak.lock();
33  if(acc->_isActive) continue;
34  lk.unlock(); // next line might call setException()...
35  acc->trigger(); // initial value
36  lk.lock();
37  acc->_isActive = true;
38  acc->_hasException = false;
39  }
40  }
42  }
43 
44  /********************************************************************************************************************/
45 
48 
49  // deactivate async transfers
50  std::unique_lock<std::mutex> lk(_pushDecoratorsMutex);
51  for(auto& pair : _pushDecorators) {
52  _pushVersions[pair.first] = {};
53  for(auto& acc_weak : pair.second) {
54  auto acc = acc_weak.lock();
55  if(!acc->_isActive) continue;
56  acc->_isActive = false;
57  if(acc->_hasException) continue;
58  acc->_hasException = true;
59  lk.unlock(); // next line might call setException()...
60  acc->trigger();
61  lk.lock();
62  }
63  }
65  }
66 
67  /********************************************************************************************************************/
68 
70  auto info = getRegisterInfo(path);
71  auto adrPair = std::make_pair(info.bar, info.address);
72  return _writeOrderMap.at(adrPair);
73  }
74 
75  /********************************************************************************************************************/
76 
78  auto info = getRegisterInfo(path);
79  auto adrPair = std::make_pair(info.bar, info.address);
80  return _writeCounterMap.at(adrPair);
81  }
82 
83  /********************************************************************************************************************/
84 
86  std::unique_lock<std::mutex> lk(_pushDecoratorsMutex);
88  }
89 
90  /********************************************************************************************************************/
91 
92  ExceptionDummy::ExceptionDummy(const std::string& mapFileName) : DummyBackend(mapFileName) {
93  OVERRIDE_VIRTUAL_FUNCTION_TEMPLATE(DummyBackendBase, getRegisterAccessor_impl);
94  }
95 
96  /********************************************************************************************************************/
97 
98  boost::shared_ptr<DeviceBackend> ExceptionDummy::createInstance(
99  // FIXME #11279 Implement API breaking changes from linter warnings
100  // NOLINTNEXTLINE(performance-unnecessary-value-param)
101  [[maybe_unused]] std::string address, std::map<std::string, std::string> parameters) {
102  if(parameters["map"].empty()) {
103  throw ChimeraTK::logic_error("No map file name given.");
104  }
105  return boost::shared_ptr<DeviceBackend>(new ExceptionDummy(parameters["map"]));
106  }
107 
108  /********************************************************************************************************************/
109 
111  if(throwExceptionOpen) {
113  setException("DummyException: open throws by request");
114  throw ChimeraTK::runtime_error("DummyException: open throws by request");
115  }
117  }
118 
119  /********************************************************************************************************************/
120 
122  setException("Close ExceptionDummy");
124  }
125 
126  /********************************************************************************************************************/
127 
128  void ExceptionDummy::read(uint64_t bar, uint64_t address, int32_t* data, size_t sizeInBytes) {
129  if(throwExceptionRead) {
131  throw ChimeraTK::runtime_error("DummyException: read throws by request");
132  }
133  ChimeraTK::DummyBackend::read(bar, address, data, sizeInBytes);
134  }
135 
136  /********************************************************************************************************************/
137 
138  void ExceptionDummy::write(uint64_t bar, uint64_t address, int32_t const* data, size_t sizeInBytes) {
139  if(throwExceptionWrite) {
141  throw ChimeraTK::runtime_error("DummyException: write throws by request");
142  }
143  ChimeraTK::DummyBackend::write(bar, address, data, sizeInBytes);
144 
145  // increment write counter and update write order (only if address points to beginning of a register!)
146  auto itWriteOrder = _writeOrderMap.find(std::make_pair(bar, address));
147  if(itWriteOrder != _writeOrderMap.end()) {
148  // update write order
149  auto generatedOrderNumber = ++_writeOrderCounter;
150  auto& orderNumberInMap = itWriteOrder->second;
151  // atomically update order number in the map only if the generated order number is bigger. This will be always
152  // the case, unless there is a concurrent write operation updating the order number in between.
153  size_t current;
154  while((current = orderNumberInMap.load()) < generatedOrderNumber) {
155  orderNumberInMap.compare_exchange_weak(current, generatedOrderNumber);
156  }
157 
158  // increment write counter
159  auto itWriteCounter = _writeCounterMap.find(std::make_pair(bar, address));
160  assert(itWriteCounter != _writeCounterMap.end()); // always inserted together
161  itWriteCounter->second++;
162  }
163  }
164 
165  /********************************************************************************************************************/
166 
167  template<typename UserType>
168  boost::shared_ptr<NDRegisterAccessor<UserType>> ExceptionDummy::getRegisterAccessor_impl(
169  const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
170  auto path = registerPathName;
171  path.setAltSeparator(".");
172  auto pathComponents = path.getComponents();
173  bool pushRead = false;
174  if(pathComponents[pathComponents.size() - 1] == "PUSH_READ") {
176  pushRead = true;
178  }
179  path--; // remove last component
180  }
181 
182  auto acc = CALL_BASE_FUNCTION_TEMPLATE(
183  DummyBackendBase, getRegisterAccessor_impl, UserType, path, numberOfWords, wordOffsetInRegister, flags);
184  if(pushRead) {
185  std::unique_lock<std::mutex> lk(_pushDecoratorsMutex);
186 
187  auto decorator = boost::make_shared<ExceptionDummyPushDecorator<UserType>>(
188  acc, boost::dynamic_pointer_cast<ExceptionDummy>(this->shared_from_this()));
189 
190  _pushDecorators[registerPathName].push_back(decorator);
191 
193  decorator->_isActive = true;
194  decorator->trigger(); // initial value
195  }
196 
197  acc = decorator;
198  }
199  else if(acc->isReadable()) {
200  // decorate all poll-type variable so returned validity of the data can be controlled
201  auto decorator = boost::make_shared<ExceptionDummyPollDecorator<UserType>>(
202  acc, boost::dynamic_pointer_cast<ExceptionDummy>(this->shared_from_this()));
203  acc = decorator;
204  }
205 
206  // create entry in _writeOrderMap and _writeCounterMap if necessary
207  if(pathComponents[pathComponents.size() - 1] != "DUMMY_WRITEABLE" &&
208  (pathComponents[0].find("DUMMY_INTERRUPT_") != 0)) {
209  auto info = getRegisterInfo(path);
210  auto adrPair = std::make_pair(info.bar, info.address);
211  if(_writeOrderMap.find(adrPair) == _writeOrderMap.end()) {
212  _writeOrderMap[adrPair] = 0;
213  _writeCounterMap[adrPair] = 0;
214  }
215  }
216 
217  acc->setExceptionBackend(shared_from_this());
218 
219  return acc;
220  }
221 
222  /********************************************************************************************************************/
223 
224 } // 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
ExceptionDummyBackend.h
ChimeraTK::DummyBackendBase::throwExceptionWrite
std::atomic< bool > throwExceptionWrite
Definition: DummyBackendBase.h:78
ChimeraTK::DummyBackendBase::DummyBackendBase
DummyBackendBase(std::string const &mapFileName)
Definition: DummyBackendBase.cc:8
ChimeraTK::DummyBackendBase
Base class for DummyBackends, provides common functionality.
Definition: DummyBackendBase.h:31
ChimeraTK::DummyBackend::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: DummyBackend.cc:61
ChimeraTK::DummyBackendBase::throwExceptionCounter
std::atomic< size_t > throwExceptionCounter
Definition: DummyBackendBase.h:79
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::DummyBackendBase::throwExceptionOpen
std::atomic< bool > throwExceptionOpen
Definition: DummyBackendBase.h:76
ChimeraTK::ExceptionDummy::createInstance
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
Definition: ExceptionDummyBackend.cc:98
ChimeraTK::ExceptionDummy::_writeOrderCounter
std::atomic< size_t > _writeOrderCounter
Global counter for order numbers going into _writeOrderMap.
Definition: ExceptionDummyBackend.h:96
ChimeraTK::AccessModeFlags::remove
void remove(AccessMode flag)
Remove the given flag from the set.
Definition: AccessMode.cc:56
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::DummyBackend::open
void open() override
Open the device.
Definition: DummyBackend.cc:21
ChimeraTK::RegisterPath::setAltSeparator
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
Definition: RegisterPath.h:37
ChimeraTK::runtime_error
Exception thrown when a runtime error has occured.
Definition: Exception.h:18
ChimeraTK::AccessModeFlags::has
bool has(AccessMode flag) const
Check if a certain flag is in the set.
Definition: AccessMode.cc:20
ChimeraTK::ExceptionDummy::_pushDecorators
std::map< RegisterPath, std::list< boost::weak_ptr< ExceptionDummyPushDecoratorBase > > > _pushDecorators
Map of active ExceptionDummyPushDecorator. Protected by _pushDecoratorMutex.
Definition: ExceptionDummyBackend.h:66
CALL_BASE_FUNCTION_TEMPLATE
#define CALL_BASE_FUNCTION_TEMPLATE(BaseClass, functionName, templateArgument,...)
Execute the virtual function template call to the base implementation of the function.
Definition: VirtualFunctionTemplate.h:78
ChimeraTK::ExceptionDummy::ExceptionDummy
ExceptionDummy(std::string const &mapFileName)
Definition: ExceptionDummyBackend.cc:92
ChimeraTK::NumericAddressedBackend::activateAsyncRead
void activateAsyncRead() noexcept override
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
Definition: NumericAddressedBackend.cc:190
ChimeraTK::AccessMode::wait_for_new_data
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.
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::DeviceBackendImpl::setException
void setException(const std::string &message) noexcept final
Set the backend into an exception state.
Definition: DeviceBackendImpl.cc:26
OVERRIDE_VIRTUAL_FUNCTION_TEMPLATE
#define OVERRIDE_VIRTUAL_FUNCTION_TEMPLATE(BaseClass, functionName)
Save the old vtable to be accessible by CALL_BASE_FUNCTION_TEMPLATE and overwrite it with the new imp...
Definition: VirtualFunctionTemplate.h:93
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::DummyBackend::read
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
Definition: DummyBackend.cc:49
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::NumericAddressedBackend::getRegisterInfo
NumericAddressedRegisterInfo getRegisterInfo(const RegisterPath &registerPathName)
getRegisterInfo returns a NumericAddressedRegisterInfo object for the given register.
Definition: NumericAddressedBackend.cc:31
ChimeraTK::RegisterPath
Class to store a register path name.
Definition: RegisterPath.h:16
ChimeraTK::ExceptionDummy::triggerPush
void triggerPush(RegisterPath path, VersionNumber v={})
Function to trigger sending values for push-type variables.
Definition: ExceptionDummyBackend.cc:10
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
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::NumericAddressedBackend::setExceptionImpl
void setExceptionImpl() noexcept override
Turn off the internal variable which remembers that async is active.
Definition: NumericAddressedBackend.cc:242
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::ExceptionDummy::closeImpl
void closeImpl() override
This closes the device, clears all internal registers, read-only settings and callback functions.
Definition: ExceptionDummyBackend.cc:121
ChimeraTK::DummyBackendBase::throwExceptionRead
std::atomic< bool > throwExceptionRead
Definition: DummyBackendBase.h:77
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::DummyBackend::closeImpl
void closeImpl() override
This closes the device, clears all internal registers, read-only settings and callback functions.
Definition: DummyBackend.cc:38
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51