11#include <ChimeraTK/cppext/future_queue.hpp>
13#include <boost/bind/bind.hpp>
14#include <boost/enable_shared_from_this.hpp>
15#include <boost/numeric/conversion/cast.hpp>
16#include <boost/shared_ptr.hpp>
17#include <boost/thread.hpp>
18#include <boost/thread/future.hpp>
29 class PersistentDataStorage;
61 class DiscardValueException {};
72 std::string description = std::string())
86 using SharedPtr = boost::shared_ptr<TransferElement>;
120 "' which is part of a TransferGroup is not allowed.");
124 "' which is part of a ReadAnyGroup is not allowed.");
126 this->readTransactionInProgress =
false;
150 "' which is part of a TransferGroup is not allowed.");
154 "' which is part of a ReadAnyGroup is not allowed.");
156 this->readTransactionInProgress =
false;
158 bool updateDataBuffer =
false;
163 bool retVal = updateDataBuffer;
188 bool updateDataBuffer =
false;
192 updateDataBuffer =
true;
194 return updateDataBuffer;
208 "' which is part of a TransferGroup is not allowed.");
210 this->writeTransactionInProgress =
false;
211 bool previousDataLost =
true;
216 handleTransferException([&] { previousDataLost =
writeTransfer(versionNumber); });
220 return previousDataLost;
230 "' which is part of a TransferGroup is not allowed.");
232 this->writeTransactionInProgress =
false;
235 bool previousDataLost =
true;
242 return previousDataLost;
280 if(setThisException) {
282 setThisException =
nullptr;
320 template<
typename Callable>
321 void handleTransferException(Callable function) {
328 catch(boost::thread_interrupted&) {
335 void readTransferAsyncWaitingImpl() {
340 catch(detail::DiscardValueException&) {
357 readTransferAsyncWaitingImpl();
382 bool readTransferAsyncNonWaitingImpl() {
387 catch(detail::DiscardValueException&) {
405 return readTransferAsyncNonWaitingImpl();
413 void preReadAndHandleExceptions(
TransferType type)
noexcept {
423 catch(boost::thread_interrupted&) {
434 if(readTransactionInProgress)
return;
437 readTransactionInProgress =
true;
454 void postReadAndHandleExceptions(
TransferType type,
bool updateDataBuffer) {
476 if(readTransactionInProgress) {
477 readTransactionInProgress =
false;
518 catch(boost::thread_interrupted&) {
532 if(writeTransactionInProgress)
return;
537 " passed to write() of TransferElement '" +
_name +
"' is less than the last version number used " +
540 writeTransactionInProgress =
true;
576 if(writeTransactionInProgress) {
577 writeTransactionInProgress =
false;
683 virtual bool mayReplaceOther(
const boost::shared_ptr<TransferElement const>& other)
const {
797 template<
typename QUEUE_TYPE>
799 dataTransportQueue.push_overwrite_exception(std::make_exception_ptr(boost::thread_interrupted()));
853 bool readTransactionInProgress{
false};
857 bool writeTransactionInProgress{
false};
Set of AccessMode flags with additional functionality for an easier handling.
bool has(AccessMode flag) const
Check if a certain flag is in the set.
Group several registers (= TransferElement) to allow waiting for an update of any of the registers.
Base class for register accessors which can be part of a TransferGroup.
bool writeTransferDestructively(ChimeraTK::VersionNumber versionNumber)
Write the data to the device.
void setDataValidity(DataValidity validity=DataValidity::ok)
Set the current DataValidity for this TransferElement.
cppext::future_queue< void > getReadQueue()
Function to get a copy of the read queue.
bool readNonBlocking()
Read the next value, if available in the input buffer.
std::string _name
Identifier uniquely identifying the TransferElement.
TransferElementID _id
The ID of this TransferElement.
ReadAnyGroup * _inReadAnyGroup
ReadAnyGroup this TransferElement has been added to, nullptr if not in a ReadAnyGroup.
virtual void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend)
Set the backend to which the exception has to be reported.
boost::shared_ptr< TransferElement > SharedPtr
A typedef for more compact syntax.
AccessModeFlags _accessModeFlags
The access mode flags for this transfer element.
DataValidity _dataValidity
The validity of the data in the application buffer.
void preRead(TransferType type)
Perform any pre-read tasks if necessary.
virtual std::list< boost::shared_ptr< TransferElement > > getInternalElements()=0
Obtain the full list of TransferElements internally used by this TransferElement.
virtual ~TransferElement()=default
Abstract base classes need a virtual destructor.
TransferElementID getId() const
Obtain unique ID for this TransferElement, see TransferElementID for details.
virtual void doPreRead(TransferType)
Backend specific implementation of preRead().
virtual void doPostRead(TransferType, bool)
Backend specific implementation of postRead().
std::string _description
Description of this variable/register.
ChimeraTK::VersionNumber getVersionNumber() const
Returns the version number that is associated with the last transfer (i.e.
virtual const std::type_info & getValueType() const =0
Returns the std::type_info for the value type of this transfer element.
virtual void setPersistentDataStorage(boost::shared_ptr< ChimeraTK::PersistentDataStorage >)
Associate a persistent data storage object to be updated on each write operation of this ProcessArray...
DataValidity dataValidity() const
Return current validity of the data.
std::exception_ptr _activeException
Exception to be rethrown in postXXX() in case hasSeenException == true Can be set via setActiveExcept...
virtual void replaceTransferElement(boost::shared_ptr< TransferElement > newElement)
Search for all underlying TransferElements which are considered identical (see sameRegister()) with t...
void postWrite(TransferType type, VersionNumber versionNumber)
Perform any post-write clean-ups if necessary.
virtual void doPostWrite(TransferType, VersionNumber)
Backend specific implementation of postWrite().
void interrupt_impl(QUEUE_TYPE &dataTransportQueue)
Implementation of interrupt()
ReadAnyGroup * getReadAnyGroup() const
Obtain the ReadAnyGroup this TransferElement is part of, or nullptr if not in a ReadAnyGroup.
void makeUniqueId()
Allow generating a unique ID from derived classes.
const std::string & getUnit() const
Returns the engineering unit.
bool isReadTransactionInProgress() const
Check whether a read transaction is in progress, i.e.
AccessModeFlags getAccessModeFlags() const
Return the AccessModeFlags for this TransferElement.
std::string _unit
Engineering unit.
TransferElement(const TransferElement &other)=delete
Copying and moving is not allowed.
virtual bool isReadable() const =0
Check if transfer element is readable.
bool writeDestructively(ChimeraTK::VersionNumber versionNumber={})
Just like write(), but allows the implementation to destroy the content of the user buffer in the pro...
bool readLatest()
Read the latest value, discarding any other update since the last read if present.
virtual void doReadTransferSynchronously()=0
Implementation version of readTransfer() for synchronous reads.
virtual bool doWriteTransferDestructively(ChimeraTK::VersionNumber versionNumber)
Implementation version of writeTransferDestructively().
VersionNumber _versionNumber
The version number of the last successful transfer.
void read()
Read the data from the device.
virtual void doPreWrite(TransferType, VersionNumber)
Backend specific implementation of preWrite().
void preWrite(TransferType type, ChimeraTK::VersionNumber versionNumber)
Transfer the data from the user buffer into the device send buffer, while converting the data from th...
bool _isInTransferGroup
Flag whether this TransferElement has been added to a TransferGroup or not.
virtual bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber)=0
Implementation version of writeTransfer().
TransferElement & operator=(TransferElement &&other)=delete
bool writeTransfer(ChimeraTK::VersionNumber versionNumber)
Write the data to the device.
static constexpr char unitNotSet[]
Constant string to be used as a unit when the unit is not provided or known.
cppext::future_queue< void > _readQueue
The queue for asynchronous read transfers.
virtual void setInReadAnyGroup(ReadAnyGroup *rag)
Set the ReadAnyGroup of which this TransferElement is part of.
bool readTransferNonBlocking()
Read the data from the device but do not fill it into the user buffer of this TransferElement.
virtual std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements()=0
Obtain the underlying TransferElements with actual hardware access.
const std::string & getDescription() const
Returns the description of this variable/register.
virtual bool isWriteable() const =0
Check if transfer element is writeable.
TransferElement(TransferElement &&other)=delete
virtual bool mayReplaceOther(const boost::shared_ptr< TransferElement const > &other) const
Check whether the TransferElement can be used in places where the TransferElement "other" is currentl...
void readTransfer()
Read the data from the device but do not fill it into the user buffer of this TransferElement.
void setActiveException(std::exception_ptr &setThisException)
Set an active exception.
bool isWriteTransactionInProgress() const
Check whether a write transaction is in progress, i.e.
boost::shared_ptr< DeviceBackend > getExceptionBackend()
Return the exception backend.
const std::string & getName() const
Returns the name that identifies the process variable.
TransferElement & operator=(const TransferElement &other)=delete
bool write(ChimeraTK::VersionNumber versionNumber={})
Write the data to device.
void postRead(TransferType type, bool updateDataBuffer)
Transfer the data from the device receive buffer into the user buffer, while converting the data into...
TransferElement(std::string name, AccessModeFlags accessModeFlags, std::string unit=std::string(unitNotSet), std::string description=std::string())
Creates a transfer element with the specified name.
boost::shared_ptr< DeviceBackend > _exceptionBackend
The backend to which the runtime_errors are reported via DeviceBackend::setException().
virtual boost::shared_ptr< TransferElement > makeCopyRegisterDecorator()=0
Create a CopyRegisterDecorator of the right type decorating this TransferElement.
virtual void interrupt()
Return from a blocking read immediately and throw boost::thread_interrupted.
virtual bool isReadOnly() const =0
Check if transfer element is read only, i.e.
virtual boost::shared_ptr< TransferElement > getHighLevelImplElement()
Obtain the highest level implementation TransferElement.
Simple class holding a unique ID for a TransferElement.
void makeUnique()
Assign an ID to this instance.
Group multiple data accessors to efficiently trigger data transfers on the whole group.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
Exception thrown when a runtime error has occured.
const char * what() const noexcept override
Return the message describing what exactly went wrong.
std::ostream & operator<<(std::ostream &stream, const DataDescriptor::FundamentalType &fundamentalType)
DataValidity
The current state of the data.
@ faulty
The data is considered valid.
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.
TransferType
Used to indicate the applicable operation on a Transferelement.