1 #ifndef CHIMERATK_DOOCS_BACKEND_REGISTER_ACCESSOR_H
2 #define CHIMERATK_DOOCS_BACKEND_REGISTER_ACCESSOR_H
7 #include <doocs/EqCall.h>
10 #include <type_traits>
12 #include <ChimeraTK/AccessMode.h>
13 #include <ChimeraTK/Exception.h>
14 #include <ChimeraTK/FixedPointConverter.h>
15 #include <ChimeraTK/MappedImage.h>
16 #include <ChimeraTK/NDRegisterAccessor.h>
17 #include <ChimeraTK/RegisterPath.h>
74 template<
typename UserType>
99 if(!
_backend->isOpen())
throw ChimeraTK::logic_error(
"Read operation not allowed while device is closed.");
100 if(!
isReadable())
throw ChimeraTK::logic_error(
"Try to read from write-only register \"" +
_path +
"\".");
104 if(!
_backend->isOpen())
throw ChimeraTK::logic_error(
"Write operation not allowed while device is closed.");
105 if(!
isWriteable())
throw ChimeraTK::logic_error(
"Try to write read-only register \"" +
_path +
"\".");
109 if(!hasNewData)
return;
118 TransferElement::setDataValidity(
dst.error() == 0 ? DataValidity::ok : DataValidity::faulty);
127 if(
dst.get_event_id() == doocs::EventId()) {
129 TransferElement::_versionNumber = {};
146 auto startVersion =
_backend->getStartVersion();
147 if(newVersionNumber < startVersion) {
148 newVersionNumber = startVersion;
155 if(newVersionNumber < TransferElement::_versionNumber) {
160 TransferElement::_versionNumber = newVersionNumber;
170 using TransferElement::_readQueue;
172 bool mayReplaceOther(
const boost::shared_ptr<TransferElement const>& other)
const override {
173 auto rhsCasted = boost::dynamic_pointer_cast<const DoocsBackendRegisterAccessor<UserType>>(other);
174 if(!rhsCasted)
return false;
175 if(
_path != rhsCasted->_path)
return false;
176 if(
nElements != rhsCasted->nElements)
return false;
182 return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
193 const std::string& registerPathName,
size_t numberOfWords,
size_t wordOffsetInRegister, AccessModeFlags flags);
216 template<
typename UserType>
218 size_t actualLength = 0;
224 if(_backend->isOpen()) {
226 rc = eq.get(&ea, &tmp, &dst);
229 if(rc == eq_errors::ill_property || rc == eq_errors::ill_location || rc == eq_errors::ill_address) {
231 throw ChimeraTK::logic_error(
"Property does not exist: " + _path);
240 actualLength = dst.array_length();
241 if(actualLength == 0 && dst.length() == 1) {
245 if(actualLength == 0) actualLength = dst.length();
248 if(typeId == DATA_IMAGE) {
250 actualLength +=
sizeof(ChimeraTK::ImgHeader);
255 if(typeId == DATA_TEXT || typeId == DATA_STRING) {
259 if(actualLength > 1) {
267 nElements = actualLength;
269 if(nElements + elementOffset > actualLength) {
271 if(typeId != DATA_IMAGE) {
272 throw ChimeraTK::logic_error(
"Requested number of words exceeds the length of the DOOCS property!");
275 if(nElements == actualLength && elementOffset == 0) {
283 NDRegisterAccessor<UserType>::buffer_2D.resize(1);
284 NDRegisterAccessor<UserType>::buffer_2D[0].resize(nElements);
287 src.set_type(typeId);
288 if(typeId == DATA_IMAGE) {
290 src.length(actualLength -
sizeof(ChimeraTK::ImgHeader));
292 else if(typeId != DATA_IIII) {
293 src.length(actualLength);
305 template<
typename UserType>
307 const std::string& path,
const std::string& registerPathName,
size_t numberOfWords,
size_t wordOffsetInRegister,
308 AccessModeFlags flags)
309 : NDRegisterAccessor<UserType>(path, flags), _isReadable(true), _isWriteable(true) {
313 elementOffset = wordOffsetInRegister;
314 nElements = numberOfWords;
318 flags.checkForUnknownFlags({AccessMode::wait_for_new_data});
324 auto info = backend->getBackendRegisterCatalogue().getBackendRegister(registerPathName);
327 if(flags.has(AccessMode::wait_for_new_data)) {
328 if(!info.getSupportedAccessModes().has(AccessMode::wait_for_new_data)) {
329 throw ChimeraTK::logic_error(
"invalid access mode for this register");
334 notifications = cppext::future_queue<doocs::EqData>(3);
335 _readQueue = notifications.then<
void>([
this](doocs::EqData& data) { this->dst = data; }, std::launch::deferred);
348 template<
typename UserType>
350 assert(shutdownCalled);
355 template<
typename UserType>
357 if(!_backend->isFunctional()) {
358 throw ChimeraTK::runtime_error(std::string(
"Exception reported by another accessor."));
363 boost::this_thread::interruption_point();
367 int rc = eq.get(&ea, &tmp, &dst);
370 if(rc && DoocsBackend::isCommunicationError(dst.error())) {
371 _backend->informRuntimeError(_path);
372 throw ChimeraTK::runtime_error(std::string(
"Cannot read from DOOCS property: ") + dst.get_string());
378 template<
typename UserType>
380 if(!_backend->isFunctional()) {
381 throw ChimeraTK::runtime_error(std::string(
"Exception reported by another accessor."));
385 int rc = eq.set(&ea, &src, &dst);
387 if(rc && (DoocsBackend::isCommunicationError(dst.error()) || (dst.error() == eq_errors::read_only))) {
388 _backend->informRuntimeError(_path);
389 if(dst.error() == eq_errors::read_only) {
390 this->_isWriteable =
false;
392 throw ChimeraTK::runtime_error(std::string(
"Cannot write to DOOCS property: ") + dst.get_string());