12 template<
typename UserType>
15 :
NDRegisterAccessor<UserType>(registerPathName, flags), _registerPathName(registerPathName),
16 _wordOffsetInRegister(wordOffsetInRegister), _flags(flags) {
18 _dev = boost::dynamic_pointer_cast<LogicalNameMappingBackend>(dev);
34 if(numberOfWords == 0) numberOfWords =
_info.
length;
37 if(wordOffsetInRegister + numberOfWords >
_info.
length) {
39 "Requested number of words and/or offset exceeds length of register '" + registerPathName +
"'.");
56 std::lock_guard<std::mutex> lock(lnmVariable.valueTable_mutex);
59 using T = decltype(arg);
60 auto& vtEntry = boost::fusion::at_key<T>(lnmVariable.valueTable.table);
62 cppext::future_queue<typename LNMVariable::ValueTable<T>::QueuedValue> queue(3);
64 vtEntry.subscriptions[this->getId()] = queue;
66 this->_readQueue = queue.template then<void>(
67 [this](const typename LNMVariable::ValueTable<T>::QueuedValue& queueValue) {
68 this->_queueValue.validity = queueValue.validity;
69 this->_queueValue.version = queueValue.version;
70 for(size_t i = 0; i < queueValue.value.size(); ++i) {
71 this->_queueValue.value[i] =
72 userTypeToUserType<UserType>(queueValue.value[i + this->_wordOffsetInRegister]);
75 std::launch::deferred);
77 if(
_dev->_asyncReadActive) {
78 queue.push({vtEntry.latestValue, vtEntry.latestValidity, vtEntry.latestVersion});
84 auto& lnmVariable = _dev->_variables[_info.name];
85 for(
auto* mp : lnmVariable.usingFormulas) {
86 if(mp->_hasPushParameter) {
88 if(!mp->_creatingFormulaHelper) {
89 auto h = mp->getFormulaHelper(_dev);
90 _formulaHelpers.push_back(h);
102 template<
typename UserType>
104 if(_flags.has(AccessMode::wait_for_new_data)) {
106 auto& lnmVariable = _dev->_variables[_info.name];
107 std::lock_guard<std::mutex> lock(lnmVariable.valueTable_mutex);
109 using T = decltype(arg);
110 auto& vtEntry = boost::fusion::at_key<T>(lnmVariable.valueTable.table);
111 vtEntry.subscriptions.erase(this->getId());
118 template<
typename UserType>
120 _dev->checkActiveException();
125 template<
typename UserType>
130 "Writing to constant-type registers of logical name mapping devices is not possible.");
139 template<
typename UserType>
141 _dev->checkActiveException();
142 auto& lnmVariable = _dev->_variables[_info.name];
143 std::lock_guard<std::mutex> lock(lnmVariable.valueTable_mutex);
146 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
149 for(size_t i = 0; i < this->buffer_2D[0].size(); ++i) {
150 vtEntry.latestValue[i + _wordOffsetInRegister] = userTypeToUserType<decltype(arg)>(this->buffer_2D[0][i]);
152 vtEntry.latestValidity = this->dataValidity();
153 vtEntry.latestVersion = v;
156 if(_dev->_asyncReadActive) {
157 for(auto& sub : vtEntry.subscriptions) {
158 sub.second.push_overwrite({vtEntry.latestValue, this->dataValidity(), v});
167 template<
typename UserType>
171 for(
const auto& h : _formulaHelpers) {
172 h->updateResult(versionNumber);
181 template<
typename UserType>
188 template<
typename UserType>
190 return _info.targetType == LNMBackendRegisterInfo::TargetType::CONSTANT;
195 template<
typename UserType>
202 template<
typename UserType>
204 return _info.targetType != LNMBackendRegisterInfo::TargetType::CONSTANT;
209 template<
typename UserType>
218 template<
typename UserType>
220 if(!hasNewData)
return;
222 if(!_flags.has(AccessMode::wait_for_new_data)) {
224 auto& lnmVariable = _dev->_variables[_info.name];
225 std::lock_guard<std::mutex> lock(lnmVariable.valueTable_mutex);
228 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
229 for(size_t i = 0; i < this->buffer_2D[0].size(); ++i) {
230 this->buffer_2D[0][i] = userTypeToUserType<UserType>(vtEntry.latestValue[i + _wordOffsetInRegister]);
232 this->_dataValidity = vtEntry.latestValidity;
237 this->_versionNumber = vtEntry.latestVersion;
242 this->buffer_2D[0].swap(_queueValue.value);
243 this->_versionNumber = _queueValue.version;
244 this->_dataValidity = _queueValue.validity;
250 template<
typename UserType>
252 auto& lnmVariable = _dev->_variables[_info.name];
253 std::lock_guard<std::mutex> lock(lnmVariable.valueTable_mutex);
256 auto& vtEntry = boost::fusion::at_key<decltype(arg)>(lnmVariable.valueTable.table);
257 auto itsub = vtEntry.subscriptions.find(this->getId());
258 if(itsub != vtEntry.subscriptions.end()) {
259 this->interrupt_impl(itsub->second);