ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
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
5namespace 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, const std::string& dataConsistencyKeyDescriptor)
93 : DummyBackend(mapFileName, dataConsistencyKeyDescriptor) {
95 }
96
97 /********************************************************************************************************************/
98
99 boost::shared_ptr<DeviceBackend> ExceptionDummy::createInstance(
100 // FIXME #11279 Implement API breaking changes from linter warnings
101 // NOLINTNEXTLINE(performance-unnecessary-value-param)
102 [[maybe_unused]] std::string address, std::map<std::string, std::string> parameters) {
103 if(parameters["map"].empty()) {
104 throw ChimeraTK::logic_error("No map file name given.");
105 }
106 return boost::shared_ptr<DeviceBackend>(new ExceptionDummy(parameters["map"]));
107 }
108
109 /********************************************************************************************************************/
110
114 setException("DummyException: open throws by request");
115 throw ChimeraTK::runtime_error("DummyException: open throws by request");
116 }
118 }
119
120 /********************************************************************************************************************/
121
123 setException("Close ExceptionDummy");
125 }
126
127 /********************************************************************************************************************/
128
129 void ExceptionDummy::read(uint64_t bar, uint64_t address, int32_t* data, size_t sizeInBytes) {
132 throw ChimeraTK::runtime_error("DummyException: read throws by request");
133 }
134 ChimeraTK::DummyBackend::read(bar, address, data, sizeInBytes);
135 }
136
137 /********************************************************************************************************************/
138
139 void ExceptionDummy::write(uint64_t bar, uint64_t address, int32_t const* data, size_t sizeInBytes) {
142 throw ChimeraTK::runtime_error("DummyException: write throws by request");
143 }
144 ChimeraTK::DummyBackend::write(bar, address, data, sizeInBytes);
145
146 // increment write counter and update write order (only if address points to beginning of a register!)
147 auto itWriteOrder = _writeOrderMap.find(std::make_pair(bar, address));
148 if(itWriteOrder != _writeOrderMap.end()) {
149 // update write order
150 auto generatedOrderNumber = ++_writeOrderCounter;
151 auto& orderNumberInMap = itWriteOrder->second;
152 // atomically update order number in the map only if the generated order number is bigger. This will be always
153 // the case, unless there is a concurrent write operation updating the order number in between.
154 size_t current;
155 while((current = orderNumberInMap.load()) < generatedOrderNumber) {
156 orderNumberInMap.compare_exchange_weak(current, generatedOrderNumber);
157 }
158
159 // increment write counter
160 auto itWriteCounter = _writeCounterMap.find(std::make_pair(bar, address));
161 assert(itWriteCounter != _writeCounterMap.end()); // always inserted together
162 itWriteCounter->second++;
163 }
164 }
165
166 /********************************************************************************************************************/
167
168 template<typename UserType>
169 boost::shared_ptr<NDRegisterAccessor<UserType>> ExceptionDummy::getRegisterAccessor_impl(
170 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
171 auto path = registerPathName;
172 path.setAltSeparator(".");
173 auto pathComponents = path.getComponents();
174 bool pushRead = false;
175 if(pathComponents[pathComponents.size() - 1] == "PUSH_READ") {
177 pushRead = true;
179 }
180 path--; // remove last component
181 }
182
184 DummyBackendBase, getRegisterAccessor_impl, UserType, path, numberOfWords, wordOffsetInRegister, flags);
185 if(pushRead) {
186 std::unique_lock<std::mutex> lk(_pushDecoratorsMutex);
187
188 auto decorator = boost::make_shared<ExceptionDummyPushDecorator<UserType>>(
189 acc, boost::dynamic_pointer_cast<ExceptionDummy>(this->shared_from_this()));
190
191 _pushDecorators[registerPathName].push_back(decorator);
192
194 decorator->_isActive = true;
195 decorator->trigger(); // initial value
196 }
197
198 acc = decorator;
199 }
200 else if(acc->isReadable()) {
201 // decorate all poll-type variable so returned validity of the data can be controlled
202 auto decorator = boost::make_shared<ExceptionDummyPollDecorator<UserType>>(
203 acc, boost::dynamic_pointer_cast<ExceptionDummy>(this->shared_from_this()));
204 acc = decorator;
205 }
206
207 // create entry in _writeOrderMap and _writeCounterMap if necessary
208 if(pathComponents[pathComponents.size() - 1] != "DUMMY_WRITEABLE" &&
209 (pathComponents[0].find("DUMMY_INTERRUPT_") != 0)) {
210 auto info = getRegisterInfo(path);
211 auto adrPair = std::make_pair(info.bar, info.address);
212 if(_writeOrderMap.find(adrPair) == _writeOrderMap.end()) {
213 _writeOrderMap[adrPair] = 0;
214 _writeCounterMap[adrPair] = 0;
215 }
216 }
217
218 acc->setExceptionBackend(shared_from_this());
219
220 return acc;
221 }
222
223 /********************************************************************************************************************/
224
225} // namespace ChimeraTK
#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...
#define CALL_BASE_FUNCTION_TEMPLATE(BaseClass, functionName, templateArgument,...)
Execute the virtual function template call to the base implementation of the function.
Set of AccessMode flags with additional functionality for an easier handling.
Definition AccessMode.h:48
void remove(AccessMode flag)
Remove the given flag from the set.
Definition AccessMode.cc:56
bool has(AccessMode flag) const
Check if a certain flag is in the set.
Definition AccessMode.cc:20
virtual void activateAsyncRead() noexcept
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
virtual void setExceptionImpl() noexcept
Function to be (optionally) implemented by backends if additional actions are needed when switching t...
void setException(const std::string &message) noexcept final
Set the backend into an exception state.
Base class for DummyBackends, provides common functionality.
std::atomic< bool > throwExceptionWrite
std::atomic< bool > throwExceptionRead
std::atomic< size_t > throwExceptionCounter
std::atomic< bool > throwExceptionOpen
The dummy device opens a mapping file instead of a device, and implements all registers defined in th...
void write(uint64_t bar, uint64_t address, int32_t const *data, size_t sizeInBytes) override
Write function to be implemented by backends.
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
void open() override
Open the device.
void closeImpl() override
This closes the device, clears all internal registers, read-only settings and callback functions.
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.
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
void open() override
Open the device.
ExceptionDummy(std::string const &mapFileName, const std::string &dataConsistencyKeyDescriptor="")
size_t getWriteOrder(const RegisterPath &path)
Function to obtain the write order number of a register.
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 write(uint64_t bar, uint64_t address, int32_t const *data, size_t sizeInBytes) override
Write function to be implemented by backends.
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.
NumericAddressedRegisterInfo getRegisterInfo(const RegisterPath &registerPathName)
getRegisterInfo returns a NumericAddressedRegisterInfo object for the given register.
Class to store a register path name.
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
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
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.