16 : hasParsed(false), _lmapFileName(std::move(lmapFileName)) {
37 for(
auto& p : reg.plugins) {
38 auto thisp = boost::static_pointer_cast<const LogicalNameMappingBackend>(shared_from_this());
39 p->postParsingHook(thisp);
66 plug->openHook(boost::dynamic_pointer_cast<LogicalNameMappingBackend>(shared_from_this()));
73 auto& variable = nameAndVar.second;
74 if(variable.isConstant) {
75 std::lock_guard<std::mutex> lk(variable.valueTable_mutex);
77 boost::fusion::at_key<decltype(v)>(variable.valueTable.table).latestVersion = versionForConstants;
109 std::string , std::map<std::string, std::string> parameters) {
111 if(parameters[
"map"].empty()) {
114 auto ptr = boost::make_shared<LogicalNameMappingBackend>(parameters[
"map"]);
115 parameters.erase(parameters.find(
"map"));
116 ptr->_parameters = parameters;
117 return boost::static_pointer_cast<DeviceBackend>(ptr);
122 template<
typename UserType>
125 size_t omitPlugins) {
128 boost::shared_ptr<NDRegisterAccessor<UserType>> returnValue;
130 if(info.plugins.size() <= omitPlugins) {
133 getRegisterAccessor_internal<UserType>(registerPathName, numberOfWords, wordOffsetInRegister, flags);
136 returnValue = info.plugins[omitPlugins]->getAccessor<UserType>(
137 boost::static_pointer_cast<LogicalNameMappingBackend>(shared_from_this()), numberOfWords,
138 wordOffsetInRegister, flags, omitPlugins);
141 returnValue->setExceptionBackend(shared_from_this());
148 template<
typename UserType>
156 if(info.length != 0) {
158 if(numberOfWords == 0) numberOfWords = info.length;
159 if((numberOfWords + wordOffsetInRegister) > info.length) {
162 "LogicalNameMappingBackend: Error creating accessor. Number of words plus offset too large in ") +
168 size_t actualOffset = size_t(info.firstIndex) + wordOffsetInRegister;
169 size_t actualLength = (numberOfWords > 0 ? numberOfWords : size_t(info.length));
172 boost::shared_ptr<NDRegisterAccessor<UserType>> ptr;
173 if(info.targetType == LNMBackendRegisterInfo::TargetType::REGISTER) {
175 std::string devName = info.deviceName;
176 if(devName !=
"this") {
177 _targetDevice =
_devices[info.deviceName].get();
180 _targetDevice =
this;
183 if(_targetDevice ==
nullptr) {
185 "exception thrown in open()!");
189 RegisterPath(info.registerName), actualLength, actualOffset, flags);
191 else if(info.targetType == LNMBackendRegisterInfo::TargetType::CHANNEL) {
193 shared_from_this(), registerPathName, actualLength, actualOffset, flags));
195 else if(info.targetType == LNMBackendRegisterInfo::TargetType::BIT) {
196 ptr = boost::shared_ptr<NDRegisterAccessor<UserType>>(
199 else if(info.targetType == LNMBackendRegisterInfo::TargetType::CONSTANT ||
200 info.targetType == LNMBackendRegisterInfo::TargetType::VARIABLE) {
202 shared_from_this(), registerPathName, actualLength, actualOffset, flags));
206 "For this register type, a RegisterAccessor cannot be obtained (name of logical register: " +
207 registerPathName +
").");
221 auto targetType = lnmInfo.targetType;
222 if(targetType != LNMBackendRegisterInfo::TargetType::REGISTER &&
223 targetType != LNMBackendRegisterInfo::TargetType::CHANNEL &&
224 targetType != LNMBackendRegisterInfo::TargetType::BIT) {
228 std::string devName = lnmInfo.deviceName;
232 if(devName !=
"this") {
233 auto cat =
_devices.at(devName)->getRegisterCatalogue();
234 if(!cat.hasRegister(lnmInfo.registerName))
continue;
235 target_info = cat.getRegister(lnmInfo.registerName);
242 for(
auto& plugin : i.plugins) {
249 if(targetType != LNMBackendRegisterInfo::TargetType::BIT) {
259 if(targetType == LNMBackendRegisterInfo::TargetType::CHANNEL) {
260 lnmInfo.writeable =
false;
263 if(targetType == LNMBackendRegisterInfo::TargetType::REGISTER) {
273 for(
auto& plugin : lnmInfo.plugins) {
285 template<
typename UserType>
289 void getRegisterAccessor_impl(
const RegisterPath& registerPathName,
size_t numberOfWords,
290 size_t wordOffsetInRegister,
AccessModeFlags flags,
size_t omitPlugins) {
294 void getRegisterAccessor_internal(
const RegisterPath& registerPathName,
size_t numberOfWords,
306 d.second->setException(message);
314 if(info.targetType == LNMBackendRegisterInfo::TargetType::VARIABLE) {
316 auto& lnmVariable = _variables[info.name];
317 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
318 for(auto& sub : vtEntry.subscriptions) {
320 throw ChimeraTK::runtime_error(message);
323 sub.second.push_overwrite_exception(std::current_exception());
332 _asyncReadActive =
false;
335 for(
auto& reg : _catalogue_mutable) {
337 plug->exceptionHook();
344 void LogicalNameMappingBackend::activateAsyncRead() noexcept {
345 if(!isFunctional())
return;
348 _asyncReadActive =
true;
351 for(
auto& d : _devices) {
352 d.second->activateAsyncRead();
357 for(
auto& r : _catalogue_mutable) {
359 if(info.targetType == LNMBackendRegisterInfo::TargetType::VARIABLE) {
360 auto& lnmVariable = _variables[info.name];
363 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
365 if(vtEntry.latestVersion < v) {
366 vtEntry.latestVersion = v;
368 for(
auto& sub : vtEntry.subscriptions) {
370 sub.second.push_overwrite({vtEntry.latestValue, vtEntry.latestValidity, vtEntry.latestVersion});
372 catch(std::system_error& e) {
373 std::cerr <<
"Caught system error in activateAsyncRead(): " << e.what() << std::endl;
379 catch(std::bad_cast& e) {
391 std::unordered_set<std::string> LogicalNameMappingBackend::getTargetDevices()
const {
392 std::unordered_set<std::string> ret;
393 for(
const auto& info : _catalogue_mutable) {
394 if(info.deviceName !=
"this" && !info.deviceName.empty()) ret.insert(info.deviceName);
402 return _versionOnOpen;