16 "doubleBuffer plugin not supported for redirectedChannel! use it with redirectedRegister instead");
29 template<
typename UserType,
typename TargetType>
33 if constexpr(std::is_same<UserType, TargetType>::value) {
34 return boost::make_shared<DoubleBufferAccessorDecorator<UserType>>(backend, target, *
this, accessorParams);
40 template<
typename UserType>
45 boost::shared_ptr<DeviceBackend> dev;
46 const auto& parameters = plugin._parameters;
48 if(plugin._targetDeviceName !=
"this") {
49 dev = backend->_devices.at(plugin._targetDeviceName);
55 catch(std::out_of_range& ex) {
56 std::string message =
"LogicalNameMappingBackend DoubleBufferPlugin: unknown targetDevice " + std::string(
"'") +
57 plugin._targetDeviceName +
"'.";
63 if(parameters.find(
"daqNumber") != parameters.end()) {
65 daqNumber = std::stoul(parameters.at(
"daqNumber"));
67 catch(std::exception& e) {
69 "LogicalNameMappingBackend DoubleBufferPlugin: parameter 'daqNumber' must be integer");
73 if(parameters.find(
"testUSleep") != parameters.end()) {
75 _testUSleep = std::stoul(parameters.at(
"testUSleep"));
77 catch(std::exception& e) {
79 "LogicalNameMappingBackend DoubleBufferPlugin: parameter 'testUSleep' must be integer");
85 _enableDoubleBufferReg =
86 dev->getRegisterAccessor<uint32_t>(parameters.at(key.assign(
"enableDoubleBuffering")), 1, daqNumber, {});
87 _currentBufferNumberReg =
88 dev->getRegisterAccessor<uint32_t>(parameters.at(key.assign(
"currentBufferNumber")), 1, daqNumber, {});
89 std::string secondBufName = parameters.at(key.assign(
"secondBuffer"));
96 auto flags = accessorParams.
_flags;
97 _secondBufferReg = dev->getRegisterAccessor<UserType>(secondBufName, numWords, offset, flags);
99 catch(std::out_of_range& ex) {
100 std::string message =
101 "LogicalNameMappingBackend DoubleBufferPlugin: Missing parameter " + std::string(
"'") + key +
"'.";
104 if(_secondBufferReg->getNumberOfChannels() != _target->getNumberOfChannels()) {
105 throw ChimeraTK::logic_error(
"LogicalNameMappingBackend DoubleBufferPlugin: shapes of first and second buffer do "
106 "not match, different number of channels");
108 if(_secondBufferReg->getNumberOfSamples() != _target->getNumberOfSamples()) {
109 throw ChimeraTK::logic_error(
"LogicalNameMappingBackend DoubleBufferPlugin: shapes of first and second buffer do "
110 "not match, different number of samples");
114 template<
typename UserType>
117 std::lock_guard lg{_plugin._readerCount.mutex};
118 _plugin._readerCount.value++;
121 _enableDoubleBufferReg->accessData(0) = 0;
122 _enableDoubleBufferReg->write();
127 boost::this_thread::sleep_for(boost::chrono::microseconds{_testUSleep});
131 _currentBufferNumberReg->read();
132 _currentBuffer = _currentBufferNumberReg->accessData(0);
136 _target->preRead(type);
139 _secondBufferReg->preRead(type);
143 template<
typename UserType>
146 _target->readTransfer();
149 _secondBufferReg->readTransfer();
153 template<
typename UserType>
156 _target->postRead(type, hasNewData);
159 _secondBufferReg->postRead(type, hasNewData);
163 std::lock_guard lg{_plugin._readerCount.mutex};
164 assert(_plugin._readerCount.value > 0);
165 _plugin._readerCount.value--;
166 if(_plugin._readerCount.value == 0) {
170 _currentBufferNumberReg->read();
171 if(_currentBuffer != _currentBufferNumberReg->accessData(0)) {
172 std::cout <<
"WARNING: buffer switch happened while reading! Expect corrupted data." << std::endl;
176 _enableDoubleBufferReg->accessData(0) = 1;
177 _enableDoubleBufferReg->write();
181 this->_versionNumber = {};
183 this->_dataValidity = _target->dataValidity();
186 this->_dataValidity = _secondBufferReg->dataValidity();
196 for(
size_t i = 0; i < _target->getNumberOfChannels(); ++i) {
201 for(
size_t i = 0; i < _secondBufferReg->getNumberOfChannels(); ++i) {
207 template<
typename UserType>
209 UserType>::getHardwareAccessingElements() {
212 return {TransferElement::shared_from_this()};
215 template<
typename UserType>
217 const boost::shared_ptr<const TransferElement>& other)
const {
220 auto otherDoubleBuffer = boost::dynamic_pointer_cast<DoubleBufferAccessorDecorator const>(other);
221 if(otherDoubleBuffer.get() ==
this) {
224 if(!otherDoubleBuffer) {
227 return &(otherDoubleBuffer->_plugin) == &_plugin;
void remove(AccessMode flag)
Remove the given flag from the set.
void setRawDataType(const DataType &d)
Set the raw data type.
@ none
The data type/concept does not exist, e.g. there is no raw transfer (do not confuse with Void)
LNMBackendRegisterInfo _info
RegisterInfo describing the the target register for which this plugin instance should work.
Base class for plugins that modify the behaviour of accessors in the logical name mapping backend.
void doReadTransferSynchronously() override
Implementation version of readTransfer() for synchronous reads.
void doPostRead(TransferType type, bool hasNewData) override
Backend specific implementation of postRead().
DoubleBufferAccessorDecorator(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< UserType > > &target, DoubleBufferPlugin &plugin, const UndecoratedParams &accessorParams)
bool mayReplaceOther(const boost::shared_ptr< TransferElement const > &other) const override
Check whether the TransferElement can be used in places where the TransferElement "other" is currentl...
void doPreRead(TransferType type) override
Backend specific implementation of preRead().
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
DoubleBufferPlugin(const LNMBackendRegisterInfo &info, size_t pluginIndex, std::map< std::string, std::string > parameters)
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
RegisterInfo structure for the LogicalNameMappingBackend.
unsigned int firstIndex
The first index in the range.
DataDescriptor _dataDescriptor
AccessModeFlags supportedFlags
Supported AccessMode flags.
bool writeable
Flag if the register is writeable.
unsigned int length
The length of the range (i.e.
std::string deviceName
The target device alias.
TargetType targetType
Type of the target.
Base class for decorators of the NDRegisterAccessor.
N-dimensional register accessor.
Exception thrown when a logic error has occured.
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
TransferType
Used to indicate the applicable operation on a Transferelement.
Helper struct to hold extra parameters needed by some plugins, used in decorateAccessor()
size_t _wordOffsetInRegister