15 : hasParsed(false), _lmapFileName(
std::move(lmapFileName)) {
38 for(
auto& p : reg.plugins) {
39 auto thisp = boost::static_pointer_cast<const LogicalNameMappingBackend>(shared_from_this());
40 p->postParsingHook(thisp);
69 plug->openHook(boost::dynamic_pointer_cast<LogicalNameMappingBackend>(shared_from_this()));
76 auto& variable = nameAndVar.second;
77 if(variable.isConstant) {
78 std::lock_guard<std::mutex> lk(variable.valueTable_mutex);
80 boost::fusion::at_key<decltype(v)>(variable.valueTable.table).latestVersion = versionForConstants;
102 if(
device.second->isOpen()) {
116 std::string , std::map<std::string, std::string> parameters) {
118 if(parameters[
"map"].empty()) {
121 auto ptr = boost::make_shared<LogicalNameMappingBackend>(parameters[
"map"]);
122 parameters.erase(parameters.find(
"map"));
123 ptr->_parameters = parameters;
124 return boost::static_pointer_cast<DeviceBackend>(ptr);
129 template<
typename UserType>
132 size_t omitPlugins) {
135 boost::shared_ptr<NDRegisterAccessor<UserType>> returnValue;
137 if(info.plugins.size() <= omitPlugins) {
140 getRegisterAccessor_internal<UserType>(registerPathName, numberOfWords, wordOffsetInRegister, flags);
143 returnValue = info.plugins[omitPlugins]->getAccessor<UserType>(
144 boost::static_pointer_cast<LogicalNameMappingBackend>(shared_from_this()), numberOfWords,
145 wordOffsetInRegister, flags, omitPlugins);
148 returnValue->setExceptionBackend(shared_from_this());
155 template<
typename UserType>
163 if(info.length != 0) {
165 if(numberOfWords == 0) {
166 numberOfWords = info.length;
168 if((numberOfWords + wordOffsetInRegister) > info.length) {
171 "LogicalNameMappingBackend: Error creating accessor. Number of words plus offset too large in ") +
177 size_t actualOffset = size_t(info.firstIndex) + wordOffsetInRegister;
178 size_t actualLength = (numberOfWords > 0 ? numberOfWords : size_t(info.length));
181 boost::shared_ptr<NDRegisterAccessor<UserType>> ptr;
184 std::string devName = info.deviceName;
185 if(devName !=
"this") {
186 _targetDevice =
_devices[info.deviceName].get();
189 _targetDevice =
this;
192 if(_targetDevice ==
nullptr) {
194 "exception thrown in open()!");
198 RegisterPath(info.registerName), actualLength, actualOffset, flags);
202 shared_from_this(), registerPathName, actualLength, actualOffset, flags));
205 ptr = boost::shared_ptr<NDRegisterAccessor<UserType>>(
211 shared_from_this(), registerPathName, actualLength, actualOffset, flags));
215 "For this register type, a RegisterAccessor cannot be obtained (name of logical register: " +
216 registerPathName +
").");
231 std::map<std::string, RegisterCatalogue> catalogueMap;
238 auto targetType = lnmInfo.targetType;
245 std::string devName = lnmInfo.deviceName;
249 if(devName !=
"this") {
250 const auto& cat = catalogueMap.at(devName);
251 if(!cat.hasRegister(lnmInfo.registerName)) {
254 target_info = cat.getRegister(lnmInfo.registerName);
261 for(
auto& plugin : i.plugins) {
279 lnmInfo.writeable =
false;
285 if(lnmInfo.length == 0) {
289 lnmInfo.tags = target_info.
getTags();
296 for(
auto& plugin : lnmInfo.plugins) {
308 template<
typename UserType>
313 void getRegisterAccessor_impl(
const RegisterPath& registerPathName,
size_t numberOfWords,
314 size_t wordOffsetInRegister,
AccessModeFlags flags,
size_t omitPlugins) {
316 registerPathName, numberOfWords, wordOffsetInRegister, std::move(flags), omitPlugins);
320 void getRegisterAccessor_internal(
const RegisterPath& registerPathName,
size_t numberOfWords,
323 registerPathName, numberOfWords, wordOffsetInRegister, std::move(flags));
333 d.second->setException(message);
343 auto& lnmVariable = _variables[info.name];
344 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
345 for(auto& sub : vtEntry.subscriptions) {
347 throw ChimeraTK::runtime_error(message);
350 sub.second.push_overwrite_exception(std::current_exception());
359 _asyncReadActive =
false;
362 for(
auto& reg : _catalogue_mutable) {
364 plug->exceptionHook();
371 void LogicalNameMappingBackend::activateAsyncRead() noexcept {
372 if(!isFunctional()) {
379 auto asyncWasActive = _asyncReadActive.exchange(
true);
385 for(
auto& d : _devices) {
386 d.second->activateAsyncRead();
391 for(
auto& r : _catalogue_mutable) {
393 if(info.targetType == LNMBackendRegisterInfo::TargetType::VARIABLE) {
394 auto& lnmVariable = _variables[info.name];
397 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
399 if(vtEntry.latestVersion < v) {
400 vtEntry.latestVersion = v;
402 for(
auto& sub : vtEntry.subscriptions) {
404 sub.second.push_overwrite({vtEntry.latestValue, vtEntry.latestValidity, vtEntry.latestVersion});
406 catch(std::system_error& e) {
407 std::cerr <<
"Caught system error in activateAsyncRead(): " << e.what() << std::endl;
413 catch(std::bad_cast& e) {
425 std::unordered_set<std::string> LogicalNameMappingBackend::getTargetDevices()
const {
426 std::unordered_set<std::string> ret;
427 for(
const auto& info : _catalogue_mutable) {
428 if(info.deviceName !=
"this" && !info.deviceName.empty()) {
429 ret.insert(info.deviceName);
438 return _versionOnOpen;
443 std::set<DeviceBackend::BackendID> LogicalNameMappingBackend::getInvolvedBackendIDs() {
445 std::set<DeviceBackend::BackendID> retVal{getBackendID()};
446 for(
auto& devIter : _devices) {
447 auto& dev = devIter.second;
448 retVal.merge(dev->getInvolvedBackendIDs());
#define INSTANTIATE_TEMPLATE_FOR_CHIMERATK_USER_TYPES(TemplateClass)
#define FILL_VIRTUAL_FUNCTION_TEMPLATE_VTABLE(functionName)
Fill the vtable of a virtual function template defined with DEFINE_VIRTUAL_FUNCTION_TEMPLATE.
Set of AccessMode flags with additional functionality for an easier handling.
static BackendFactory & getInstance()
Static function to get an instance of factory.
boost::shared_ptr< DeviceBackend > createBackend(const std::string &aliasOrUri)
Create a new backend and return the instance as a shared pointer.
Class describing the actual payload data format of a register in an abstract manner.
The base class for backends providing IO functionality for the Device class.
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor(const RegisterPath ®isterPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
Get a NDRegisterAccessor object from the register name.
bool isFunctional() const noexcept final
Return whether a device is working as intended, usually this means it is opened and does not have any...
void setOpenedAndClearException() noexcept
Backends should call this function at the end of a (successful) open() call.
std::string getActiveExceptionMessage() noexcept
std::atomic< bool > _opened
flag if backend is opened
void close()
Close the device.
RegisterCatalogue getRegisterCatalogue() const
Return the register catalogue with detailed information on all registers.
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
RegisterInfo structure for the LogicalNameMappingBackend.
Logical name map: store information from xlmap file and provide it to the LogicalNameMappingBackend a...
BackendRegisterCatalogue< LNMBackendRegisterInfo > parseFile(const std::string &fileName)
parse the given XML file
Backend to map logical register names onto real hardware registers.
BackendRegisterCatalogue< LNMBackendRegisterInfo > _catalogue_mutable
We need to make the catalogue mutable, since we fill it within getRegisterCatalogue()
std::unordered_set< std::string > getTargetDevices() const
Obtain list of all target devices referenced in the catalogue.
bool hasParsed
flag if already parsed
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
void parse() const
parse the logical map file, if not yet done
RegisterCatalogue getRegisterCatalogue() const override
Return the register catalogue with detailed information on all registers.
std::map< std::string, boost::shared_ptr< DeviceBackend > > _devices
map of target devices
LogicalNameMappingBackend(std::string lmapFileName="")
std::atomic< bool > _asyncReadActive
Flag storing whether asynchronous read has been activated.
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor_internal(const RegisterPath ®isterPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
void close() override
Close the device.
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor_impl(const RegisterPath ®isterPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags, size_t omitPlugins=0)
void setExceptionImpl() noexcept override
Function to be (optionally) implemented by backends if additional actions are needed when switching t...
void open() override
Open the device.
std::map< std::string, LNMVariable > _variables
Map of variables and constants.
bool catalogueCompleted
Flag whether the catalogue has already been filled with extra information from the target backends.
std::map< std::string, std::string > _parameters
map of parameters passed through the CDD
std::string _lmapFileName
name of the logical map file
Catalogue of register information.
bool isWriteable() const
Return whether the register is writeable.
BackendRegisterInfoBase & getImpl()
Return a reference to the implementation object.
unsigned int getNumberOfChannels() const
Return number of channels in register.
const DataDescriptor & getDataDescriptor() const
Return desciption of the actual payload data for this register.
std::set< std::string > getTags() const
Get the list of tags that are associated with this register.
AccessModeFlags getSupportedAccessModes() const
Return all supported AccessModes for this register.
unsigned int getNumberOfElements() const
Return number of elements per channel.
bool isReadable() const
Return whether the register is readable.
Class to store a register path name.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
void callForType(const std::type_info &type, LAMBDATYPE lambda)
Helper function for running code which uses some compile-time type that is specified at runtime as a ...
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...