ChimeraTK-DeviceAccess  03.18.00
testDoubleBuffering.cpp
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 
4 #define BOOST_TEST_DYN_LINK
5 #define BOOST_TEST_MODULE SubdeviceBackendUnifiedTest
6 #include <boost/test/unit_test.hpp>
7 using namespace boost::unit_test_framework;
8 
9 #include "Device.h"
10 #include "DummyBackend.h"
11 #include "ExceptionDummyBackend.h"
12 #include "TransferGroup.h"
13 #include "UnifiedBackendTest.h"
14 
15 #include <boost/thread/barrier.hpp>
16 
17 using namespace ChimeraTK;
18 
19 BOOST_AUTO_TEST_SUITE(DoubleBufferingBackendUnifiedTestSuite)
20 
21 /**********************************************************************************************************************/
22 
23 
29  using ExceptionDummy::ExceptionDummy;
30 
31  static boost::shared_ptr<DeviceBackend> createInstance(std::string, std::map<std::string, std::string> parameters) {
32  return returnInstance<DummyForDoubleBuffering>(
33  parameters.at("map"), convertPathRelativeToDmapToAbs(parameters.at("map")));
34  }
35 
39  "DummyForDoubleBuffering", &DummyForDoubleBuffering::createInstance, {"map"});
40  }
41  };
42 
43  void read(uint64_t bar, uint64_t address, int32_t* data, size_t sizeInBytes) override {
44  // Note, although ExceptionDummy::read() cannot be called concurrently with read or write from the
45  // fw simulating side, this limitation should not matter here since we only interrupt
46  // DummyForDoubleBuffering::read() and not it's base implementation
47 
48  for(unsigned i = 0; i < 2; i++) {
49  if(blockNextRead[i]) {
50  blockedInRead[i].wait();
51  unblockRead[i].wait();
52  blockNextRead[i] = false;
53  }
54  }
55  // finalize reading by calling Exception backend read
56  ChimeraTK::ExceptionDummy::read(bar, address, data, sizeInBytes);
57  }
58  // use this to request that next read blocks.
59  // array index corresponds to that of barrier arrays
60  // We know that read is called only 2nd after write (for the buffer-switching enable ctrl register),
61  // so in this sense it requests blocking after only part of the double-buffer read operation is done
62  static thread_local bool blockNextRead[2];
63  // one pair of barriers per reader thread
64  // after request that read blocks, you must wait on this
65  std::array<boost::barrier, 2> blockedInRead{boost::barrier{2}, boost::barrier{2}};
66  // use this to unblock the read
67  std::array<boost::barrier, 2> unblockRead{boost::barrier{2}, boost::barrier{2}};
68 };
69 thread_local bool DummyForDoubleBuffering::blockNextRead[2] = {false, false};
70 
71 static DummyForDoubleBuffering::BackendRegisterer gDFDBRegisterer;
72 
73 static std::string rawDeviceCdd("(DummyForDoubleBuffering?map=doubleBuffer.map)");
74 std::string lmap = "(logicalNameMap?map=doubleBuffer.xlmap&target=" + rawDeviceCdd + ")";
75 static auto backdoor =
76  boost::dynamic_pointer_cast<ExceptionDummy>(BackendFactory::getInstance().createBackend(rawDeviceCdd));
77 
78 /**********************************************************************************************************************/
79 
80 template<typename Register>
81 struct AreaType : Register {
82  static uint32_t _currentBufferNumber;
83 
84  bool isWriteable() { return false; }
85  bool isReadable() { return true; }
86  ChimeraTK::AccessModeFlags supportedFlags() { return {/* TODO later: ChimeraTK::AccessMode::wait_for_new_data */}; }
87  size_t nChannels() { return 1; }
88  size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
89  size_t nRuntimeErrorCases() { return 1; }
90 
91  static constexpr auto capabilities = TestCapabilities<>()
93  .disableAsyncReadInconsistency()
94  .disableTestWriteNeverLosesData()
95  .disableSwitchReadOnly()
96  .disableSwitchWriteOnly()
97  .disableTestRawTransfer();
98 
99  template<typename UserType>
100  std::vector<std::vector<UserType>> generateValue() {
101  auto values = this->getRemoteValue<typename Register::minimumUserType>();
102  for(size_t i = 0; i < this->nChannels(); ++i)
103  for(size_t j = 0; j < this->nElementsPerChannel(); ++j) {
104  values[i][j] += this->increment * (i + j + 1);
105  }
106  return values;
107  }
108 
109  template<typename UserType>
110  std::vector<std::vector<UserType>> getRemoteValue(bool = false) {
111  // For Variables we don't have a backdoor. We have to use the normal read and write
112  // functions which are good enough. It seems like a self consistency test, but all
113  // functionality the variable has to provide is that I can write something, and
114  // read it back, which is tested with it.
115 
116  // We might have to open the backend to perform the operation. We have to remember
117  // that we did so and close it again it we did. Some tests require the backend to be closed.
118 
119  auto currentBufferNumber = backdoor->getRegisterAccessor<uint32_t>("APP.0.WORD_DUB_BUF_CURR", 0, 0, {});
120  auto buffer0 = backdoor->getRegisterAccessor<typename Register::minimumUserType>(
121  "APP/0/DAQ0_BUF0", this->nElementsPerChannel(), 0, {});
122  auto buffer1 = backdoor->getRegisterAccessor<typename Register::minimumUserType>(
123  "APP/0/DAQ0_BUF1", this->nElementsPerChannel(), 0, {});
124 
125  bool deviceWasOpened = false;
126  if(!backdoor->isOpen()) {
127  backdoor->open();
128  deviceWasOpened = true;
129  }
130 
131  boost::shared_ptr<NDRegisterAccessor<typename Register::minimumUserType>> currentBuffer;
132 
133  currentBufferNumber->read();
134 
135  if(currentBufferNumber->accessData(0) == 1) {
136  currentBuffer = buffer0;
137  }
138  else {
139  currentBuffer = buffer1;
140  }
141  currentBuffer->read();
142  std::vector<std::vector<UserType>> v;
143  for(size_t i = 0; i < this->nChannels(); ++i) {
144  v.push_back(std::vector<UserType>());
145  for(size_t j = 0; j < this->nElementsPerChannel(); ++j) {
146  v[i].push_back(currentBuffer->accessData(j));
147  }
148  }
149 
150  if(deviceWasOpened) {
151  backdoor->close();
152  }
153 
154  return v;
155  }
156 
157  void setRemoteValue() {
158  auto currentBufferNumber = backdoor->getRegisterAccessor<uint32_t>("APP.0.WORD_DUB_BUF_CURR", 0, 0, {});
159  auto buffer0 = backdoor->getRegisterAccessor<typename Register::minimumUserType>(
160  "APP/0/DAQ0_BUF0", this->nElementsPerChannel(), 0, {});
161  auto buffer1 = backdoor->getRegisterAccessor<typename Register::minimumUserType>(
162  "APP/0/DAQ0_BUF1", this->nElementsPerChannel(), 0, {});
163  boost::shared_ptr<NDRegisterAccessor<typename Register::minimumUserType>> currentBuffer;
164 
165  bool deviceWasOpened = false;
166  if(!backdoor->isOpen()) {
167  backdoor->open();
168  deviceWasOpened = true;
169  }
170 
171  currentBufferNumber->accessData(0) = _currentBufferNumber;
172  currentBufferNumber->write();
173  _currentBufferNumber = _currentBufferNumber ? 0 : 1; // change current buffer no. 0->1 or 1->0
174 
175  auto values = this->generateValue<typename Register::minimumUserType>();
176 
177  if(currentBufferNumber->accessData(0) == 1) {
178  currentBuffer = buffer0;
179  }
180  else {
181  currentBuffer = buffer1;
182  }
183  for(size_t i = 0; i < this->nChannels(); ++i) {
184  for(size_t j = 0; j < this->nElementsPerChannel(); ++j) {
185  currentBuffer->accessData(i, j) = values[i][j];
186  }
187  }
188  currentBuffer->write();
189 
190  if(deviceWasOpened) {
191  backdoor->close();
192  }
193  }
194 
195  void setForceRuntimeError(bool enable, size_t caseNumber) {
196  if(caseNumber == 0) {
197  backdoor->throwExceptionRead = enable;
198  backdoor->throwExceptionOpen = enable;
199  }
200  }
201 };
202 
203 /**********************************************************************************************************************/
204 
205 struct MyArea1 {
206  std::string path() { return "/doubleBuffer"; }
207  size_t nElementsPerChannel() { return 10; }
208  size_t address() { return 20; }
209  int32_t increment = 3;
210 
211  typedef uint32_t minimumUserType;
212  typedef int32_t rawUserType;
213 };
214 
215 /**********************************************************************************************************************/
216 
217 template<typename Register>
219 
220 BOOST_AUTO_TEST_CASE(testUnified) {
222 }
223 
226  boost::shared_ptr<NDRegisterAccessor<uint32_t>> doubleBufferingEnabled;
227  // we call the backend doubleBufDummy when we modify the behavior of the thread which reads via double buffering mechanism
228  boost::shared_ptr<DummyForDoubleBuffering> doubleBufDummy;
230  // before any access, also via backdoor, must open
231  d.open();
232  doubleBufDummy = boost::dynamic_pointer_cast<DummyForDoubleBuffering>(backdoor);
233  assert(doubleBufDummy);
234  doubleBufferingEnabled = backdoor->getRegisterAccessor<uint32_t>("APP/0/WORD_DUB_BUF_ENA", 0, 0, {});
235  doubleBufferingEnabled->accessData(0) = 1;
236  doubleBufferingEnabled->write();
237  }
238 };
239 
241  /*
242  * Test race condition: slow reader, which blocks the Firmware from buffer switching.
243  */
244  auto accessor = d.getOneDRegisterAccessor<uint32_t>("/doubleBuffer");
245 
246  // make double buffer operation block after write to ctrl register, at read of buffer number
247  std::thread s([&] {
248  // this thread reads from double-buffered region
249  doubleBufDummy->blockNextRead[0] = true;
250  accessor.read();
251  });
252 
253  // wait that thread s is in blocked double-buffer read
254  doubleBufDummy->blockedInRead[0].wait();
255 
256  // simplification: instead of writing fw simulation which would overwrite data now,
257  // just check that buffer switching was disabled
258  doubleBufferingEnabled->readLatest();
259  BOOST_CHECK(!doubleBufferingEnabled->accessData(0));
260 
261  doubleBufDummy->unblockRead[0].wait();
262  s.join();
263 
264  // check that buffer switching enabled, by finalization of double-buffered read
265  doubleBufferingEnabled->readLatest();
266  BOOST_CHECK(doubleBufferingEnabled->accessData(0));
267 }
268 
270  /*
271  * A test which exposes the dangerous race condition of two readers
272  * - reader A deactivates buffer switching, starts reading buffer0
273  * - reader B (again) deactivates buffer switching, starts reading buffer0
274  * - reader A finished with reading, activates buffer switching already, which is too early
275  * here the correct double buffering implementation would need to wait on reader B
276  * - firmware writes into buffer1 and when done, switches buffers
277  * the writing may have started earlier (e.g. before reader A started reading), important here is
278  * only buffer switch at end
279  * - firmware writes into buffer0 and corrupts data
280  * - reader B finishes reading, and gets corrupt data, enables buffer switching.
281  */
282 
283  // wait on "reader B has started" and then wait on "reader A has finished" inside reader B
284 
285  std::thread readerA([&] {
286  auto accessor = d.getOneDRegisterAccessor<uint32_t>("/doubleBuffer");
287  // begin read
288  doubleBufDummy->blockNextRead[0] = true;
289  accessor.read();
290  });
291  std::thread readerB([&] {
292  auto accessor = d.getOneDRegisterAccessor<uint32_t>("/doubleBuffer");
293  // wait that readerA is in blocked double-buffer read
294  doubleBufDummy->blockedInRead[0].wait();
295  // begin read
296  doubleBufDummy->blockNextRead[1] = true;
297  accessor.read();
298  });
299  doubleBufDummy->blockedInRead[1].wait(); // wait that reader B also in blocked read
300  doubleBufDummy->unblockRead[0].wait(); // this is for reader A
301  readerA.join();
302 
303  // check that after reader A returned, buffer switching is still disabled
304  doubleBufferingEnabled->readLatest();
305  BOOST_CHECK(!doubleBufferingEnabled->accessData(0));
306 
307  doubleBufDummy->unblockRead[1].wait(); // this is for reader B
308  // check that after reader B returned, buffer switching is enabled
309  readerB.join();
310  doubleBufferingEnabled->readLatest();
311  BOOST_CHECK(doubleBufferingEnabled->accessData(0));
312 }
313 
318 template<class Derived>
320  const std::string rawDeviceCdd = "(dummy?map=doubleBuffer.map)";
321  const std::string lmap = "(logicalNameMap?map=doubleBuffer.xlmap&target=" + this->rawDeviceCdd + ")";
323  boost::shared_ptr<DeviceBackend> backdoor;
324  boost::shared_ptr<NDRegisterAccessor<uint32_t>> doubleBufferingEnabled, writingBufferNum;
325  boost::shared_ptr<NDRegisterAccessor<float>> buf0, buf1;
326  struct ConfigParams {
327  std::string enableDoubleBufferingReg, currentBufferNumberReg, firstBufferReg, secondBufferReg;
328  size_t daqNumber; // must match xlmap
329  };
330 
331  DeviceFixture2D() : d(this->lmap) {
332  ConfigParams c = static_cast<Derived*>(this)->getCf();
333  // before any access, also via backdoor, must open
334  d.open();
335  backdoor = BackendFactory::getInstance().createBackend(this->rawDeviceCdd);
336  doubleBufferingEnabled = backdoor->getRegisterAccessor<uint32_t>(c.enableDoubleBufferingReg, 1, c.daqNumber, {});
337  doubleBufferingEnabled->accessData(0) = 1;
338  doubleBufferingEnabled->write();
339 
340  writingBufferNum = backdoor->getRegisterAccessor<uint32_t>(c.currentBufferNumberReg, 1, c.daqNumber, {});
341  buf0 = backdoor->getRegisterAccessor<float>(c.firstBufferReg, 0, 0, {});
342  buf1 = backdoor->getRegisterAccessor<float>(c.secondBufferReg, 0, 0, {});
343  }
344 
345  void simpleCheckExtractedChannels(std::string readerAReg) {
346  /*
347  * simple test for access to extracted channels of multiplexed 2D region
348  */
349  writingBufferNum->accessData(0) = 1;
350  writingBufferNum->write();
351 
352  float modulation = 4.2; // example data
353  unsigned channel = 3; // must match with xlmap
354  buf0->accessData(channel, 0) = modulation;
355  buf1->accessData(channel, 0) = 2 * modulation;
356  buf0->write();
357  buf1->write();
358 
359  boost::barrier waitForBufferSwapStart{2}, waitForBufferSwapDone{2};
360  std::thread readerA([&] {
361  auto accessorA = d.getOneDRegisterAccessor<float>(readerAReg);
362  accessorA.readLatest();
363  // since writingBufferNum = 1, we expect buf0 contents to be read
364  BOOST_CHECK_CLOSE(accessorA[0], modulation, 1e-4);
365  waitForBufferSwapStart.wait();
366  waitForBufferSwapDone.wait();
367  accessorA.readLatest();
368  BOOST_CHECK_CLOSE(accessorA[0], 2 * modulation, 1e-4);
369  });
370 
371  waitForBufferSwapStart.wait();
372  writingBufferNum->accessData(0) = 0;
373  writingBufferNum->write();
374  waitForBufferSwapDone.wait();
375 
376  readerA.join();
377  }
378 
379  void checkExtractedChannels(std::string readerAReg, std::string readerBReg) {
380  /*
381  * test access to extracted channels of multiplexed 2D region
382  * this is an application of concurrent readers
383  */
384 
385  writingBufferNum->accessData(0) = 1;
386  writingBufferNum->write();
387 
388  float modulation = 4.2; // example data series 1
389  float correction = 10.1; // example data series 2
390  buf0->accessData(3, 0) = modulation;
391  buf1->accessData(3, 0) = 2 * modulation;
392  buf0->accessData(1, 0) = correction;
393  buf1->accessData(1, 0) = 2 * correction;
394  buf0->write();
395  buf1->write();
396 
397  boost::barrier waitForBufferSwap{3};
398 
399  // since BOOST.Test is not thread-safe, need to buffer check results in main thread
400  bool readerA_ok1, readerA_ok2, readerB_ok1, readerB_ok2;
401 
402  std::thread readerA([&] {
403  auto accessorA = d.getOneDRegisterAccessor<float>(readerAReg);
404  accessorA.readLatest();
405  readerA_ok1 = abs(accessorA[0] - modulation) < 1e-4;
406  waitForBufferSwap.wait();
407  waitForBufferSwap.wait();
408  accessorA.readLatest();
409  readerA_ok2 = abs(accessorA[0] - 2 * modulation) < 1e-4;
410  });
411  std::thread readerB([&] {
412  auto accessorB = d.getOneDRegisterAccessor<float>(readerBReg);
413  accessorB.read();
414  readerB_ok1 = abs(accessorB[0] - correction) < 1e-4;
415  waitForBufferSwap.wait();
416  waitForBufferSwap.wait();
417  accessorB.read();
418  readerB_ok2 = abs(accessorB[0] - 2 * correction) < 1e-4;
419  });
420 
421  waitForBufferSwap.wait();
422  writingBufferNum->accessData(0) = 0;
423  writingBufferNum->write();
424  waitForBufferSwap.wait();
425 
426  readerA.join();
427  readerB.join();
428  BOOST_CHECK(readerA_ok1);
429  BOOST_CHECK(readerA_ok2);
430  BOOST_CHECK(readerB_ok1);
431  BOOST_CHECK(readerB_ok2);
432 
433  // Check that also reading from a TransferGroup works
434  TransferGroup tg;
435  auto accessorA = d.getOneDRegisterAccessor<float>(readerAReg);
436  auto accessorB = d.getOneDRegisterAccessor<float>(readerBReg);
437  tg.addAccessor(accessorA);
438  tg.addAccessor(accessorB);
439  tg.read();
440  BOOST_CHECK_CLOSE(accessorA[0], 2 * modulation, 1e-4);
441  BOOST_CHECK_CLOSE(accessorB[0], 2 * correction, 1e-4);
442  // swap back to first value set
443  writingBufferNum->accessData(0) = 1;
444  writingBufferNum->write();
445  tg.read();
446  BOOST_CHECK_CLOSE(accessorA[0], modulation, 1e-4);
447  BOOST_CHECK_CLOSE(accessorB[0], correction, 1e-4);
448  }
449 };
450 
451 struct DeviceFixture2D_DAQ0 : public DeviceFixture2D<DeviceFixture2D_DAQ0> {
452  ConfigParams getCf() {
453  ConfigParams c;
454  c.enableDoubleBufferingReg = "DAQ0/WORD_DUB_BUF_ENA";
455  c.currentBufferNumberReg = "DAQ0/WORD_DUB_BUF_CURR/DUMMY_WRITEABLE";
456  c.firstBufferReg = "APP0/DAQ0_BUF0";
457  c.secondBufferReg = "APP0/DAQ0_BUF1";
458  c.daqNumber = 0;
459  return c;
460  }
461 };
462 struct DeviceFixture2D_DAQ2 : public DeviceFixture2D<DeviceFixture2D_DAQ2> {
463  ConfigParams getCf() {
464  ConfigParams c;
465  c.enableDoubleBufferingReg = "DAQ2/WORD_DUB_BUF_ENA";
466  c.currentBufferNumberReg = "DAQ2/WORD_DUB_BUF_CURR/DUMMY_WRITEABLE";
467  c.firstBufferReg = "APP2/DAQ2_BUF0";
468  c.secondBufferReg = "APP2/DAQ2_BUF1";
469  c.daqNumber = 2;
470  return c;
471  }
472 };
473 
475  // config variant: double buffering on lowest level
476  simpleCheckExtractedChannels("modulationA");
477  checkExtractedChannels("modulationA", "correctionA");
478 }
479 
481  // config variant: double buffering applied to logical registers
482  simpleCheckExtractedChannels("modulationC");
483  checkExtractedChannels("modulationC", "correctionC");
484 }
485 
486 /**********************************************************************************************************************/
487 
488 BOOST_AUTO_TEST_SUITE_END()
ExceptionDummyBackend.h
DummyForDoubleBuffering::createInstance
static boost::shared_ptr< DeviceBackend > createInstance(std::string, std::map< std::string, std::string > parameters)
Definition: testDoubleBuffering.cpp:31
ChimeraTK::ExceptionDummy
Definition: ExceptionDummyBackend.h:23
AreaType
Definition: testDoubleBuffering.cpp:81
TransferGroup.h
MyArea1::address
size_t address()
Definition: testDoubleBuffering.cpp:208
DeviceFixture2D::buf1
boost::shared_ptr< NDRegisterAccessor< float > > buf1
Definition: testDoubleBuffering.cpp:325
ChimeraTK::Device::getOneDRegisterAccessor
OneDRegisterAccessor< UserType > getOneDRegisterAccessor(const RegisterPath &registerPathName, size_t numberOfWords=0, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a OneDRegisterAccessor object for the given register.
Definition: Device.h:273
AreaType::nChannels
size_t nChannels()
Definition: testDoubleBuffering.cpp:87
ChimeraTK::BackendFactory::getInstance
static BackendFactory & getInstance()
Static function to get an instance of factory.
Definition: BackendFactory.cc:191
DeviceFixture2D::ConfigParams
Definition: testDoubleBuffering.cpp:326
DummyBackend.h
DeviceFixture2D::ConfigParams::secondBufferReg
std::string secondBufferReg
Definition: testDoubleBuffering.cpp:327
ChimeraTK::TransferGroup::addAccessor
void addAccessor(TransferElementAbstractor &accessor)
Add a register accessor to the group.
Definition: TransferGroup.cc:305
DeviceFixture::DeviceFixture
DeviceFixture()
Definition: testDoubleBuffering.cpp:229
AreaType::supportedFlags
ChimeraTK::AccessModeFlags supportedFlags()
Definition: testDoubleBuffering.cpp:86
DeviceFixture2D::checkExtractedChannels
void checkExtractedChannels(std::string readerAReg, std::string readerBReg)
Definition: testDoubleBuffering.cpp:379
ChimeraTK::TestCapabilities
Descriptor for the test capabilities for each register.
Definition: UnifiedBackendTest.h:54
DummyForDoubleBuffering::blockNextRead
static thread_local bool blockNextRead[2]
Definition: testDoubleBuffering.cpp:62
DeviceFixture2D::ConfigParams::daqNumber
size_t daqNumber
Definition: testDoubleBuffering.cpp:328
AreaType::generateValue
std::vector< std::vector< UserType > > generateValue()
Definition: testDoubleBuffering.cpp:100
ChimeraTK::TransferGroup
Group multiple data accessors to efficiently trigger data transfers on the whole group.
Definition: TransferGroup.h:26
AreaType::nRuntimeErrorCases
size_t nRuntimeErrorCases()
Definition: testDoubleBuffering.cpp:89
ChimeraTK::TransferGroup::read
void read()
Trigger read transfer for all accessors in the group.
Definition: TransferGroup.cc:44
MyArea1
Definition: testDoubleBuffering.cpp:205
MyArea1::minimumUserType
uint32_t minimumUserType
Definition: testDoubleBuffering.cpp:211
BOOST_FIXTURE_TEST_CASE
BOOST_FIXTURE_TEST_CASE(testSlowReader, DeviceFixture)
Definition: testDoubleBuffering.cpp:240
AreaType::isReadable
bool isReadable()
Definition: testDoubleBuffering.cpp:85
DeviceFixture2D
DeviceFixture used for the 2D access tests here no overwriting of ExceptionBackend.
Definition: testDoubleBuffering.cpp:319
DeviceFixture2D_DAQ0::getCf
ConfigParams getCf()
Definition: testDoubleBuffering.cpp:452
MyArea1::path
std::string path()
Definition: testDoubleBuffering.cpp:206
DeviceFixture2D_DAQ0
Definition: testDoubleBuffering.cpp:451
ChimeraTK::ExceptionDummy::read
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
Definition: ExceptionDummyBackend.cc:128
AreaType::setForceRuntimeError
void setForceRuntimeError(bool enable, size_t caseNumber)
Definition: testDoubleBuffering.cpp:195
Device.h
DeviceFixture2D::backdoor
boost::shared_ptr< DeviceBackend > backdoor
Definition: testDoubleBuffering.cpp:323
DummyForDoubleBuffering::BackendRegisterer
Definition: testDoubleBuffering.cpp:36
DeviceFixture2D::simpleCheckExtractedChannels
void simpleCheckExtractedChannels(std::string readerAReg)
Definition: testDoubleBuffering.cpp:345
ChimeraTK::UnifiedBackendTest
Class to test any backend for correct behaviour.
Definition: UnifiedBackendTest.h:259
DeviceFixture::doubleBufDummy
boost::shared_ptr< DummyForDoubleBuffering > doubleBufDummy
Definition: testDoubleBuffering.cpp:228
AreaType::setRemoteValue
void setRemoteValue()
Definition: testDoubleBuffering.cpp:157
DeviceFixture::d
Device d
Definition: testDoubleBuffering.cpp:225
lmap
std::string lmap
Definition: testDoubleBuffering.cpp:74
DeviceFixture2D_DAQ2::getCf
ConfigParams getCf()
Definition: testDoubleBuffering.cpp:463
ChimeraTK::TestCapabilities::disableForceDataLossWrite
constexpr TestCapabilities< _syncRead, TestCapability::disabled, _asyncReadInconsistency, _switchReadOnly, _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue, _setRemoteValueIncrementsVersion > disableForceDataLossWrite() const
Definition: UnifiedBackendTest.h:81
ChimeraTK::Device
Class allows to read/write registers from device.
Definition: Device.h:39
MyArea1::rawUserType
int32_t rawUserType
Definition: testDoubleBuffering.cpp:212
DeviceFixture2D::writingBufferNum
boost::shared_ptr< NDRegisterAccessor< uint32_t > > writingBufferNum
Definition: testDoubleBuffering.cpp:324
DummyForDoubleBuffering::BackendRegisterer::BackendRegisterer
BackendRegisterer()
Definition: testDoubleBuffering.cpp:37
ChimeraTK::Device::open
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition: Device.cc:58
AreaType::getRemoteValue
std::vector< std::vector< UserType > > getRemoteValue(bool=false)
Definition: testDoubleBuffering.cpp:110
DeviceFixture2D::d
Device d
Definition: testDoubleBuffering.cpp:322
DummyForDoubleBuffering
dummy backend used for testing the double buffering handshake.
Definition: testDoubleBuffering.cpp:28
AreaType::isWriteable
bool isWriteable()
Definition: testDoubleBuffering.cpp:84
AreaType::writeQueueLength
size_t writeQueueLength()
Definition: testDoubleBuffering.cpp:88
MyArea1::nElementsPerChannel
size_t nElementsPerChannel()
Definition: testDoubleBuffering.cpp:207
AreaType::_currentBufferNumber
static uint32_t _currentBufferNumber
Definition: testDoubleBuffering.cpp:82
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(testUnified)
Definition: testDoubleBuffering.cpp:220
ChimeraTK::AccessModeFlags
Set of AccessMode flags with additional functionality for an easier handling.
Definition: AccessMode.h:48
ChimeraTK::BackendFactory::registerBackendType
void registerBackendType(const std::string &backendType, boost::shared_ptr< DeviceBackend >(*creatorFunction)(std::string address, std::map< std::string, std::string > parameters), const std::vector< std::string > &sdmParameterNames={}, const std::string &deviceAccessVersion=CHIMERATK_DEVICEACCESS_VERSION)
Register a backend by the name backendType with the given creatorFunction.
Definition: BackendFactory.cc:45
DummyForDoubleBuffering::read
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
Definition: testDoubleBuffering.cpp:43
ChimeraTK
Definition: DummyBackend.h:16
UnifiedBackendTest.h
DeviceFixture2D_DAQ2
Definition: testDoubleBuffering.cpp:462
DeviceFixture::doubleBufferingEnabled
boost::shared_ptr< NDRegisterAccessor< uint32_t > > doubleBufferingEnabled
Definition: testDoubleBuffering.cpp:226
ChimeraTK::UnifiedBackendTest::addRegister
UnifiedBackendTest< typename boost::mpl::push_back< VECTOR_OF_REGISTERS_T, REG_T >::type > addRegister()
Add a register to be used by the test.
Definition: UnifiedBackendTest.h:352
DeviceFixture
Definition: testDoubleBuffering.cpp:224
DeviceFixture2D::DeviceFixture2D
DeviceFixture2D()
Definition: testDoubleBuffering.cpp:331