ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
DataConsistencyDecorator.cc
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
4
5#include <boost/pointer_cast.hpp>
6
7namespace ChimeraTK {
8
9 template<typename UserType>
11 const boost::shared_ptr<NDRegisterAccessor<UserType>>& target,
13 : NDRegisterAccessorDecorator<UserType, UserType>(target), _hGroup(dGroup) {
14 this->_inReadAnyGroup = target->getReadAnyGroup();
15 this->_readQueue = target->getReadQueue().template then<void>([this]() { readCallback(); }, std::launch::deferred);
16 }
17
18 /********************************************************************************************************************/
19
20 template<typename UserType>
22 _hGroup->handleMissingPreReads(this->getId());
23 _target->preRead(type);
24 }
25
26 /********************************************************************************************************************/
27
28 template<typename UserType>
30 // In special case that we have consistent state with unchanged version number, we do not update other
31 // decorator buffers.
32 // E.g. assume that all decorators are in consistent state, say v3.
33 // Now A gets a new update, v4. This is put into history, and since there is no value yet for matching B,
34 // we throw DiscardValueException. Assume then, we get another value for B, with version v3.
35 // In this case, decorator(A) must not be swapped again, but decorator(B) should be swapped with target(B)=v3
36 if(_hGroup->lastMatchingVersionNumber() > this->_versionNumber) {
37 _hGroup->handleMissingPostReads(this->getId(), updateDataBuffer);
38 }
39
40 // we overwrite implementation of base class NDRegisterAccessorDecorator because we
41 // update target user buffer already in readCallback, and then must not call target->postRead again here,
42 // unless an exception originates from target->queue or its continuation(readCallback).
43 if(this->_activeException) {
44 _target->setActiveException(this->_activeException);
45 _target->postRead(type, false);
46 }
47
48 // Decorators have to copy meta data even if updateDataBuffer is false
49 auto transferElementId = this->getId();
50 this->_hGroup->getMatchingInfo(transferElementId, this->_versionNumber, this->_dataValidity);
51 assert(this->_versionNumber > VersionNumber{0});
52
53 if(!updateDataBuffer) {
54 return;
55 }
56
57 auto& matchingBuffer = this->_hGroup->template getMatchingBuffer<UserType>(transferElementId);
58 for(size_t i = 0; i < _target->getNumberOfChannels(); ++i) {
59 buffer_2D[i].swap(matchingBuffer[i]);
60 }
61 }
62
63 /********************************************************************************************************************/
64
65 template<typename UserType>
67 // While ReadAnyGroup.waitAny() already calls preRead at the beginning, waitAnyNonBlocking() does not,
68 // and fist peeks into the readQueue, causing readCallback() to be executed first.
69 // We call preRead just to be sure; if called twice no harm done.
70 // Using TransferType::read should be fine even in non-blocking case, since
71 // readCallback is only executed when we know something is in target's readQueue.
72 _target->preRead(TransferType::read);
73
74 // Before we update target buffer, we swap it into history. If history buffers = {h1, h2}, then switch h1<->h2,
75 // target<->h1, so target oldest data (h2) which may be overwritten next. In match search (after
76 // postRead), the three buffers {target, h1, h2} should be searched.
77 _hGroup->updateHistory(_target->getId());
78
79 // Differently from usual decorator behavior, we call target->postRead already here,
80 // because we need user buffer content to judge data consistency.
81 _target->postRead(TransferType::read, true);
82
83 // check data consistency, including history, and update user buffers if necessary
84 bool consistent = _hGroup->checkUpdate(_target->getId());
85 if(!consistent) {
86 // if not consistent, delay call to postRead (called from ReadAnyGroup), by throwing DiscardValueException.
87 // Then, ReadAnyGroup leaves out postRead and next preRead.
88 // In order to get another update for target, need to call preRead here.
89 _target->preRead(TransferType::read);
90 throw detail::DiscardValueException();
91 }
92 }
93
94 /********************************************************************************************************************/
95
96} // namespace ChimeraTK
97
#define INSTANTIATE_TEMPLATE_FOR_CHIMERATK_USER_TYPES(TemplateClass)
A quasi-decorator to be used to decorate targets which should provide data updates only when data is ...
void doPostRead(TransferType type, bool updateDataBuffer) override
Backend specific implementation of postRead().
void doPreRead(TransferType type) override
Backend specific implementation of preRead().
DataConsistencyDecorator(const boost::shared_ptr< NDRegisterAccessor< UserType > > &target, DataConsistencyGroupDetail::HistorizedMatcher *dGroup)
Data consistency matching via history of available data.
Base class for decorators of the NDRegisterAccessor.
N-dimensional register accessor.
ReadAnyGroup * _inReadAnyGroup
ReadAnyGroup this TransferElement has been added to, nullptr if not in a ReadAnyGroup.
cppext::future_queue< void > _readQueue
The queue for asynchronous read transfers.
Class for generating and holding version numbers without exposing a numeric representation.
TransferType
Used to indicate the applicable operation on a Transferelement.