ChimeraTK-DeviceAccess  03.18.00
AsyncNDRegisterAccessor.h
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
3 #pragma once
4 
5 #include "../DeviceBackend.h"
6 #include "../NDRegisterAccessor.h"
7 #include "Domain.h"
8 
9 #include <ChimeraTK/cppext/finally.hpp>
10 #include <ChimeraTK/cppext/future_queue.hpp>
11 
12 namespace ChimeraTK::async {
13 
14  class AsyncAccessorManager;
15 
22  template<typename UserType>
23  class AsyncNDRegisterAccessor : public NDRegisterAccessor<UserType> {
24  static constexpr size_t _queueSize{3};
25 
26  public:
31  AsyncNDRegisterAccessor(boost::shared_ptr<DeviceBackend> backend, boost::shared_ptr<AsyncAccessorManager> manager,
32  boost::shared_ptr<Domain> asyncDomain, std::string const& name, size_t nChannels, size_t nElements,
33  AccessModeFlags accessModeFlags, std::string const& unit = std::string(TransferElement::unitNotSet),
34  std::string const& description = std::string());
35 
36  ~AsyncNDRegisterAccessor() override;
37 
41  void sendException(std::exception_ptr& e) { _dataTransportQueue.push_overwrite_exception(e); }
42 
47 
49  // implementation of inherited, virtual functions //
51 
52  void doReadTransferSynchronously() override {
53  // This code should never be executed because the constructor checks that wait_for_new_data is set.
54  assert(false);
55  }
56 
57  bool doWriteTransfer([[maybe_unused]] ChimeraTK::VersionNumber versionNumber) override {
58  assert(false);
59  return false;
60  }
61 
62  bool doWriteTransferDestructively([[maybe_unused]] ChimeraTK::VersionNumber versionNumber) override {
63  assert(false);
64  return false;
65  }
66 
67  void doPreWrite([[maybe_unused]] TransferType type, [[maybe_unused]] VersionNumber versionNumber) override {
68  throw ChimeraTK::logic_error("Writing is not supported for " + this->getName());
69  }
70 
71  void doPreRead([[maybe_unused]] TransferType type) override {
72  if(!_backend->isOpen()) throw ChimeraTK::logic_error("Device not opened.");
73  // Pre-read conceptually does nothing in asynchronous reads
74  }
75 
76  // Don't ask my why in template code the [[maybe_unused]] must be here, but gives a warning when put to the
77  // implementation.
78  void doPostRead([[maybe_unused]] TransferType type, bool updateDataBuffer) override;
79 
80  [[nodiscard]] bool isReadOnly() const override {
81  return !isWriteable(); // as the accessor is always readable, isReadOnly() is equivalent to !isWriteable()
82  }
83  [[nodiscard]] bool isReadable() const override { return true; }
84  [[nodiscard]] bool isWriteable() const override { return false; }
85 
86  void setExceptionBackend(boost::shared_ptr<DeviceBackend> exceptionBackend) override {
87  this->_exceptionBackend = exceptionBackend;
88  }
89 
90  std::vector<boost::shared_ptr<TransferElement>> getHardwareAccessingElements() override {
91  return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
92  }
93  std::list<boost::shared_ptr<TransferElement>> getInternalElements() override { return {}; }
94 
95  void replaceTransferElement(boost::shared_ptr<TransferElement> /*newElement*/) override {} // LCOV_EXCL_LINE
96 
97  void interrupt() override { this->interrupt_impl(this->_dataTransportQueue); }
98 
99  protected:
100  boost::shared_ptr<DeviceBackend> _backend;
101  boost::shared_ptr<AsyncAccessorManager> _accessorManager;
102  boost::shared_ptr<Domain> _asyncDomain;
106 
107  cppext::future_queue<Buffer, cppext::SWAP_DATA> _dataTransportQueue{_queueSize};
108  };
109 
110  /********************************************************************************************************************/
111  /* Implementations are in the .cc file. We use the trick to declare for all known types here, */
112  /* and instantiate all of them in the .cc file. This is necessary because we cannot include */
113  /* AsyncAccessorManager.h to avoid a circular dependency, but need it for the implementation. */
114  /********************************************************************************************************************/
115  DECLARE_TEMPLATE_FOR_CHIMERATK_USER_TYPES(AsyncNDRegisterAccessor);
116 
117 } // namespace ChimeraTK::async
ChimeraTK::async::AsyncNDRegisterAccessor::doReadTransferSynchronously
void doReadTransferSynchronously() override
Definition: AsyncNDRegisterAccessor.h:52
ChimeraTK::async::AsyncNDRegisterAccessor::getHardwareAccessingElements
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Definition: AsyncNDRegisterAccessor.h:90
ChimeraTK::async::AsyncNDRegisterAccessor
The AsyncNDRegisterAccessor implements a data transport queue with typed data as continuation of the ...
Definition: AsyncNDRegisterAccessor.h:23
Domain.h
ChimeraTK::async::AsyncNDRegisterAccessor::isWriteable
bool isWriteable() const override
Definition: AsyncNDRegisterAccessor.h:84
ChimeraTK::async::AsyncNDRegisterAccessor::getInternalElements
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Definition: AsyncNDRegisterAccessor.h:93
ChimeraTK::async
Definition: design_AsyncNDRegisterAcessor_and_NumericAddressedBackend.dox:1
ChimeraTK::async::AsyncNDRegisterAccessor::AsyncNDRegisterAccessor
AsyncNDRegisterAccessor(boost::shared_ptr< DeviceBackend > backend, boost::shared_ptr< AsyncAccessorManager > manager, boost::shared_ptr< Domain > asyncDomain, std::string const &name, size_t nChannels, size_t nElements, AccessModeFlags accessModeFlags, std::string const &unit=std::string(TransferElement::unitNotSet), std::string const &description=std::string())
In addition to the arguments of the NDRegisterAccessor constructor, you need an AsyncAccessorManager ...
Definition: AsyncNDRegisterAccessor.cc:16
ChimeraTK::async::AsyncNDRegisterAccessor::replaceTransferElement
void replaceTransferElement(boost::shared_ptr< TransferElement >) override
Definition: AsyncNDRegisterAccessor.h:95
ChimeraTK::async::DECLARE_TEMPLATE_FOR_CHIMERATK_USER_TYPES
DECLARE_TEMPLATE_FOR_CHIMERATK_USER_TYPES(AsyncNDRegisterAccessor)
ChimeraTK::async::AsyncNDRegisterAccessor::~AsyncNDRegisterAccessor
~AsyncNDRegisterAccessor() override
Definition: AsyncNDRegisterAccessor.cc:11
ChimeraTK::async::AsyncNDRegisterAccessor::_accessorManager
boost::shared_ptr< AsyncAccessorManager > _accessorManager
Definition: AsyncNDRegisterAccessor.h:101
ChimeraTK::async::AsyncNDRegisterAccessor::sendException
void sendException(std::exception_ptr &e)
Pushes the exception to the queue.
Definition: AsyncNDRegisterAccessor.h:41
ChimeraTK::async::AsyncNDRegisterAccessor::doPreRead
void doPreRead([[maybe_unused]] TransferType type) override
Definition: AsyncNDRegisterAccessor.h:71
ChimeraTK::async::AsyncNDRegisterAccessor::_asyncDomain
boost::shared_ptr< Domain > _asyncDomain
Definition: AsyncNDRegisterAccessor.h:102
ChimeraTK::TransferElement::unitNotSet
static constexpr char unitNotSet[]
Constant string to be used as a unit when the unit is not provided or known.
Definition: TransferElement.h:742
ChimeraTK::async::AsyncNDRegisterAccessor::_dataTransportQueue
cppext::future_queue< Buffer, cppext::SWAP_DATA > _dataTransportQueue
Definition: AsyncNDRegisterAccessor.h:107
ChimeraTK::async::AsyncNDRegisterAccessor::sendDestructively
void sendDestructively(typename NDRegisterAccessor< UserType >::Buffer &data)
You can only send destructively.
Definition: AsyncNDRegisterAccessor.cc:65
ChimeraTK::async::AsyncNDRegisterAccessor::interrupt
void interrupt() override
Definition: AsyncNDRegisterAccessor.h:97
ChimeraTK::async::AsyncNDRegisterAccessor::_backend
boost::shared_ptr< DeviceBackend > _backend
Definition: AsyncNDRegisterAccessor.h:100
ChimeraTK::async::AsyncNDRegisterAccessor::doWriteTransferDestructively
bool doWriteTransferDestructively([[maybe_unused]] ChimeraTK::VersionNumber versionNumber) override
Definition: AsyncNDRegisterAccessor.h:62
ChimeraTK::TransferType
TransferType
Used to indicate the applicable operation on a Transferelement.
Definition: TransferElement.h:51
ChimeraTK::async::AsyncNDRegisterAccessor::isReadOnly
bool isReadOnly() const override
Definition: AsyncNDRegisterAccessor.h:80
ChimeraTK::async::AsyncNDRegisterAccessor::setExceptionBackend
void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend) override
Definition: AsyncNDRegisterAccessor.h:86
ChimeraTK::async::AsyncNDRegisterAccessor::_receiveBuffer
Buffer _receiveBuffer
Definition: AsyncNDRegisterAccessor.h:105
ChimeraTK::async::AsyncNDRegisterAccessor::doWriteTransfer
bool doWriteTransfer([[maybe_unused]] ChimeraTK::VersionNumber versionNumber) override
Definition: AsyncNDRegisterAccessor.h:57
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
ChimeraTK::AccessModeFlags
Set of AccessMode flags with additional functionality for an easier handling.
Definition: AccessMode.h:48
ChimeraTK::async::AsyncNDRegisterAccessor::doPreWrite
void doPreWrite([[maybe_unused]] TransferType type, [[maybe_unused]] VersionNumber versionNumber) override
Definition: AsyncNDRegisterAccessor.h:67
ChimeraTK::async::AsyncNDRegisterAccessor::isReadable
bool isReadable() const override
Definition: AsyncNDRegisterAccessor.h:83
ChimeraTK::NDRegisterAccessor::Buffer
Data type to create individual buffers.
Definition: NDRegisterAccessor.h:86
ChimeraTK::async::AsyncNDRegisterAccessor::doPostRead
void doPostRead([[maybe_unused]] TransferType type, bool updateDataBuffer) override
Definition: AsyncNDRegisterAccessor.cc:47
ChimeraTK::NDRegisterAccessor
N-dimensional register accessor.
Definition: ForwardDeclarations.h:17
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51