11 :
AccessorPlugin(info, pluginIndex), _parameters(std::move(parameters)) {
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();
189 if(!hasNewData)
return;
192 for(
size_t i = 0; i < _target->getNumberOfChannels(); ++i) {
197 for(
size_t i = 0; i < _secondBufferReg->getNumberOfChannels(); ++i) {
203 template<
typename UserType>
205 UserType>::getHardwareAccessingElements() {
208 return {TransferElement::shared_from_this()};
211 template<
typename UserType>
213 const boost::shared_ptr<const TransferElement>& other)
const {
216 auto otherDoubleBuffer = boost::dynamic_pointer_cast<DoubleBufferAccessorDecorator const>(other);
217 if(!otherDoubleBuffer) {
220 return &(otherDoubleBuffer->_plugin) == &_plugin;