ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
BackendRegisterCatalogue.h
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#pragma once
4
6#include "RegisterCatalogue.h"
7
8#include <boost/make_shared.hpp>
9#include <boost/range/adaptors.hpp>
10
11namespace ChimeraTK {
12
13 template<typename BackendRegisterInfo>
14 class const_BackendRegisterCatalogueImplIterator;
15
16 template<typename BackendRegisterInfo>
17 class BackendRegisterCatalogueImplIterator;
18
19 /********************************************************************************************************************/
20 /* Register catalogue container class definitions ******************************************************************/
21 /********************************************************************************************************************/
22
25 public:
27
29
31
32 virtual ~BackendRegisterCatalogueBase() = default;
33
34 // Copy constructor/assignment is deleted. It could be implemented (need to take care of pointers in
35 // insertionOrderedCatalogue), but currently there is no need for this and hence it is not done.
38
44 [[nodiscard]] virtual RegisterInfo getRegister(const RegisterPath& registerPathName) const = 0;
45
47 [[nodiscard]] virtual bool hasRegister(const RegisterPath& registerPathName) const = 0;
48
50 [[nodiscard]] virtual size_t getNumberOfRegisters() const = 0;
51
53 [[nodiscard]] virtual std::unique_ptr<const_RegisterCatalogueImplIterator> getConstIteratorBegin() const = 0;
54
56 [[nodiscard]] virtual std::unique_ptr<const_RegisterCatalogueImplIterator> getConstIteratorEnd() const = 0;
57
66 [[nodiscard]] virtual std::unique_ptr<BackendRegisterCatalogueBase> clone() const = 0;
67
72 [[nodiscard]] virtual std::shared_ptr<async::DataConsistencyRealm> getDataConsistencyRealm(
73 const std::vector<size_t>& qualifiedAsyncDomainId) const;
74
81 const std::vector<size_t>& qualifiedAsyncDomainId) const;
82
83 [[nodiscard]] virtual HiddenRange hiddenRegisters() const = 0;
84 };
85
86 /********************************************************************************************************************/
87
95 template<typename BackendRegisterInfo>
97 public:
100 [[nodiscard]] virtual BackendRegisterInfo getBackendRegister(const RegisterPath& registerPathName) const;
101
102 [[nodiscard]] bool hasRegister(const RegisterPath& registerPathName) const override;
103
105 [[nodiscard]] RegisterInfo getRegister(const RegisterPath& registerPathName) const final;
106
107 // Return the number of registers in the catalogue, excluding hidden registers.
108 [[nodiscard]] size_t getNumberOfRegisters() const override;
109
110 [[nodiscard]] std::unique_ptr<const_RegisterCatalogueImplIterator> getConstIteratorBegin() const override;
111
112 [[nodiscard]] std::unique_ptr<const_RegisterCatalogueImplIterator> getConstIteratorEnd() const override;
113
114 [[nodiscard]] std::unique_ptr<BackendRegisterCatalogueBase> clone() const override;
115
120 void addRegister(const BackendRegisterInfo& registerInfo);
121
126 void removeRegister(const RegisterPath& name);
127
136 void modifyRegister(const BackendRegisterInfo& registerInfo);
137
142
147
152
157
162
167
171 [[nodiscard]] HiddenRange hiddenRegisters() const override {
172 auto filtered = _catalogue | boost::adaptors::filtered([](auto const& kv) { return kv.second.isHidden(); }) |
173 boost::adaptors::transformed([](const auto& kv) -> const BackendRegisterInfoBase& { return kv.second; });
174
175 return HiddenRange(filtered.begin(), filtered.end());
176 }
177
178 protected:
189
190 private:
191 // Always access the catalogue through the member functions. Modifications need special care to keep the two
192 // containers synchronised, hence these members are made private.
193 // The map _catalogue should contain all registers, including "hidden" ones. An exception might be "dynamic"
194 // registers which only exist when someone is looking for them (potentially with time-dependent behaviour). Also
195 // some backends might still implement "hidden" registers without filling them here.
196 std::map<RegisterPath, BackendRegisterInfo> _catalogue;
197
198 // The _iteratedCatalogue is used to the present the user the registers in a nice way, excluding "hidden" registers.
199 // It will be ordered by insertion (call to addRegister()), so e.g. the ordering in the map file can be kept.
200 std::vector<BackendRegisterInfo*> _iteratedCatalogue;
201 };
202
203 /********************************************************************************************************************/
204 /* Iterator class definitions **************************************************************************************/
205 /********************************************************************************************************************/
206
225 template<typename BackendRegisterInfo>
227 public:
228 explicit const_BackendRegisterCatalogueImplIterator(typename std::vector<BackendRegisterInfo*>::const_iterator it);
229
230 void increment() override;
231
232 void decrement() override;
233
234 const BackendRegisterInfoBase* get() override;
235
236 [[nodiscard]] bool isEqual(
237 const std::unique_ptr<const_RegisterCatalogueImplIterator>& rightHandSide) const override;
238
239 [[nodiscard]] std::unique_ptr<const_RegisterCatalogueImplIterator> clone() const override;
240
242
244
246
248
249 const BackendRegisterInfo& operator*() const;
250
251 const BackendRegisterInfo* operator->() const;
252
253 explicit operator RegisterCatalogue::const_iterator() const;
254
255 bool operator==(const const_BackendRegisterCatalogueImplIterator& rightHandSide) const;
256
257 bool operator!=(const const_BackendRegisterCatalogueImplIterator& rightHandSide) const;
258
259 protected:
260 typename std::vector<BackendRegisterInfo*>::const_iterator theIterator;
261 };
262
263 /********************************************************************************************************************/
264
266 template<typename BackendRegisterInfo>
268 public:
270
271 explicit BackendRegisterCatalogueImplIterator(typename std::vector<BackendRegisterInfo*>::iterator theIterator_);
272
274
276
278
280
281 BackendRegisterInfo& operator*() const;
282
283 BackendRegisterInfo* operator->() const;
284
285 explicit operator RegisterCatalogue::const_iterator() const;
286
287 bool operator==(const BackendRegisterCatalogueImplIterator& rightHandSide) const;
288
289 bool operator!=(const BackendRegisterCatalogueImplIterator& rightHandSide) const;
290
291 protected:
292 typename std::vector<BackendRegisterInfo*>::iterator theIterator;
293 };
294
295 /********************************************************************************************************************/
296 /********************************************************************************************************************/
297
298 /********************************************************************************************************************/
299 /* Register catalogue container implementations ********************************************************************/
300 /********************************************************************************************************************/
301
302 template<typename BackendRegisterInfo>
304 return RegisterInfo(std::make_unique<BackendRegisterInfo>(getBackendRegister(name)));
305 }
306
307 /********************************************************************************************************************/
308
309 template<typename BackendRegisterInfo>
311 const RegisterPath& name) const {
312 try {
313 return _catalogue.at(name);
314 }
315 catch(std::out_of_range&) {
316 throw ChimeraTK::logic_error("BackendRegisterCatalogue::getRegister(): Register '" + name + "' does not exist.");
317 }
318 }
319
320 /********************************************************************************************************************/
321
322 template<typename BackendRegisterInfo>
324 return _catalogue.find(registerPathName) != _catalogue.end();
325 }
326
327 /********************************************************************************************************************/
328
329 template<typename BackendRegisterInfo>
331 return _iteratedCatalogue.size();
332 }
333
334 /********************************************************************************************************************/
335
336 template<typename BackendRegisterInfo>
337 std::unique_ptr<const_RegisterCatalogueImplIterator> BackendRegisterCatalogue<
338 BackendRegisterInfo>::getConstIteratorBegin() const {
339 auto it =
340 std::make_unique<const_BackendRegisterCatalogueImplIterator<BackendRegisterInfo>>(_iteratedCatalogue.cbegin());
341 return it;
342 }
343
344 /********************************************************************************************************************/
345
346 template<typename BackendRegisterInfo>
347 std::unique_ptr<const_RegisterCatalogueImplIterator> BackendRegisterCatalogue<
348 BackendRegisterInfo>::getConstIteratorEnd() const {
349 auto it =
350 std::make_unique<const_BackendRegisterCatalogueImplIterator<BackendRegisterInfo>>(_iteratedCatalogue.cend());
351 return it;
352 }
353
354 /********************************************************************************************************************/
355
356 template<typename BackendRegisterInfo>
357 std::unique_ptr<BackendRegisterCatalogueBase> BackendRegisterCatalogue<BackendRegisterInfo>::clone() const {
358 // FIXME: Change BackendRegisterCatalogue to CRTP, i.e. it has the DERIVED class as template parameter.
359 // Like this the correct catalogue type is already created here and inheriting backends can call this clone,
360 // then cast to the actual type and fill the rest of it's properties. Would get rid of the "fillFromThis()"
361 // workaround and safe clone() implementations in case no data members are added.
362
363 // Create a new instance of a BackendRegisterCatalogue with the correct type.
364 // Inheriting backends will create the derrived type here.
365 std::unique_ptr<BackendRegisterCatalogueBase> c = std::make_unique<BackendRegisterCatalogue<BackendRegisterInfo>>();
366 // Fill the contents of the BackendRegisterCatalogue base class into the target c. This is accessing the
367 // private variables and ensures consistency.
368 fillFromThis(dynamic_cast<BackendRegisterCatalogue<BackendRegisterInfo>*>(c.get()));
369 // Derived backends will copy/clone their additional data members here, before
370 // returning the unique_ptr. The compiler will return it via copy elision.
371 return c;
372 }
373
374 /********************************************************************************************************************/
375
376 template<typename BackendRegisterInfo>
379 // copy all registers, including hidden registers
380 for(auto& p : _catalogue) {
381 target->_catalogue[p.first] = getBackendRegister(p.first);
382 }
383 // create insertion-order-correct vector of non-hidden registers, pointing to the new RegisterInfo copies
384 for(auto& ptr : _iteratedCatalogue) {
385 target->_iteratedCatalogue.push_back(&target->_catalogue[ptr->getRegisterName()]);
386 }
387 }
388
389 /********************************************************************************************************************/
390
391 template<typename BackendRegisterInfo>
392 void BackendRegisterCatalogue<BackendRegisterInfo>::addRegister(const BackendRegisterInfo& registerInfo) {
393 if(hasRegister(registerInfo.getRegisterName())) {
394 throw ChimeraTK::logic_error("BackendRegisterCatalogue::addRegister(): Register with the name " +
395 registerInfo.getRegisterName() + " already exists!");
396 }
397 _catalogue[registerInfo.getRegisterName()] = registerInfo;
398 if(!registerInfo.isHidden()) {
399 _iteratedCatalogue.push_back(&_catalogue[registerInfo.getRegisterName()]);
400 }
401 }
402
403 /********************************************************************************************************************/
404
405 template<typename BackendRegisterInfo>
407 // check existence
408 if(!hasRegister(name)) {
410 "BackendRegisterCatalogue::removeRegister(): Register '" + name + "' does not exist.");
411 }
412
413 // remove from insertion-ordered vector
414 auto it = std::find_if(
415 _iteratedCatalogue.begin(), _iteratedCatalogue.end(), [&](auto reg) { return reg->getRegisterName() == name; });
416 assert(it != _iteratedCatalogue.end());
417 _iteratedCatalogue.erase(it);
418
419 // remove from catalogue map
420 auto removed = _catalogue.erase(name);
421 assert(removed == 1);
422 }
423
424 /********************************************************************************************************************/
425
426 template<typename BackendRegisterInfo>
427 void BackendRegisterCatalogue<BackendRegisterInfo>::modifyRegister(const BackendRegisterInfo& registerInfo) {
428 if(!hasRegister(registerInfo.getRegisterName())) {
429 throw ChimeraTK::logic_error("BackendRegisterCatalogue::modifyRegister(): Register '" +
430 registerInfo.getRegisterName() + "' cannot be modified because it does not exist!");
431 }
432 _catalogue[registerInfo.getRegisterName()] = registerInfo;
433 // We don't have to touch the insertionOrderedCatalogue because is stores references, and this has not changed.
434 }
435
436 /********************************************************************************************************************/
437 /* Iterator implementations ****************************************************************************************/
438 /********************************************************************************************************************/
439
440 template<typename BackendRegisterInfo>
442 typename std::vector<BackendRegisterInfo*>::const_iterator it)
443 : theIterator(it) {}
444
445 /********************************************************************************************************************/
446
447 template<typename BackendRegisterInfo>
451
452 /********************************************************************************************************************/
453
454 template<typename BackendRegisterInfo>
458
459 /********************************************************************************************************************/
460
461 template<typename BackendRegisterInfo>
465
466 /********************************************************************************************************************/
467
468 template<typename BackendRegisterInfo>
470 const std::unique_ptr<const_RegisterCatalogueImplIterator>& rightHandSide) const {
471 auto rhs_casted = dynamic_cast<const_BackendRegisterCatalogueImplIterator*>(rightHandSide.get());
472 return rhs_casted && rhs_casted->theIterator == theIterator;
473 }
474
475 /********************************************************************************************************************/
476
477 template<typename BackendRegisterInfo>
478 std::unique_ptr<const_RegisterCatalogueImplIterator> const_BackendRegisterCatalogueImplIterator<
479 BackendRegisterInfo>::clone() const {
480 return {std::make_unique<const_BackendRegisterCatalogueImplIterator>(*this)};
481 }
482
483 /********************************************************************************************************************/
484
485 template<typename BackendRegisterInfo>
487 BackendRegisterInfo>::operator++() {
488 ++theIterator;
489 return *this;
490 }
491
492 /********************************************************************************************************************/
493
494 template<typename BackendRegisterInfo>
496 BackendRegisterInfo>::operator++(int) {
498 ++theIterator;
499 return temp;
500 }
501
502 /********************************************************************************************************************/
503
504 template<typename BackendRegisterInfo>
506 BackendRegisterInfo>::operator--() {
507 --theIterator;
508 return *this;
509 }
510
511 /********************************************************************************************************************/
512
513 template<typename BackendRegisterInfo>
515 BackendRegisterInfo>::operator--(int) {
517 --theIterator;
518 return temp;
519 }
520
521 /********************************************************************************************************************/
522
523 template<typename BackendRegisterInfo>
525 return *(*theIterator);
526 }
527
528 /********************************************************************************************************************/
529
530 template<typename BackendRegisterInfo>
532 return *theIterator;
533 }
534
535 /********************************************************************************************************************/
536
537 template<typename BackendRegisterInfo>
539 const const_BackendRegisterCatalogueImplIterator& rightHandSide) const {
540 return rightHandSide.theIterator == theIterator;
541 }
542
543 /********************************************************************************************************************/
544
545 template<typename BackendRegisterInfo>
547 const const_BackendRegisterCatalogueImplIterator& rightHandSide) const {
548 return rightHandSide.theIterator != theIterator;
549 }
550
551 /********************************************************************************************************************/
552 /********************************************************************************************************************/
553
554 template<typename BackendRegisterInfo>
556 typename std::vector<BackendRegisterInfo*>::iterator theIterator_)
557 : theIterator(theIterator_) {}
558
559 /********************************************************************************************************************/
560
561 template<typename BackendRegisterInfo>
563 BackendRegisterInfo>::operator++() {
564 ++theIterator;
565 return *this;
566 }
567
568 /********************************************************************************************************************/
569
570 template<typename BackendRegisterInfo>
572 BackendRegisterInfo>::operator++(int) {
574 ++theIterator;
575 return temp;
576 }
577
578 /********************************************************************************************************************/
579
580 template<typename BackendRegisterInfo>
582 BackendRegisterInfo>::operator--() {
583 --theIterator;
584 return *this;
585 }
586
587 /********************************************************************************************************************/
588
589 template<typename BackendRegisterInfo>
591 BackendRegisterInfo>::operator--(int) {
593 --theIterator;
594 return temp;
595 }
596
597 /********************************************************************************************************************/
598
599 template<typename BackendRegisterInfo>
601 return *(*theIterator);
602 }
603
604 /********************************************************************************************************************/
605
606 template<typename BackendRegisterInfo>
608 return *theIterator;
609 }
610
611 /********************************************************************************************************************/
612
613 template<typename BackendRegisterInfo>
616 boost::make_shared<const_BackendRegisterCatalogueImplIterator<BackendRegisterInfo>>(theIterator)};
617 }
618
619 /********************************************************************************************************************/
620
621 template<typename BackendRegisterInfo>
623 const BackendRegisterCatalogueImplIterator& rightHandSide) const {
624 return rightHandSide.theIterator == theIterator;
625 }
626
627 /********************************************************************************************************************/
628
629 template<typename BackendRegisterInfo>
631 const BackendRegisterCatalogueImplIterator& rightHandSide) const {
632 return rightHandSide.theIterator != theIterator;
633 }
634
635 /********************************************************************************************************************/
636
637} // namespace ChimeraTK
Pure virtual implementation base class for the register catalogue.
virtual ~BackendRegisterCatalogueBase()=default
virtual std::shared_ptr< async::DataConsistencyRealm > getDataConsistencyRealm(const std::vector< size_t > &qualifiedAsyncDomainId) const
Return DataConsistencyRealm for the given qualified AsyncDomainId.
BackendRegisterCatalogueBase & operator=(const BackendRegisterCatalogueBase &other)=delete
BackendRegisterCatalogueBase(BackendRegisterCatalogueBase &&other)=default
BackendRegisterCatalogueBase(const BackendRegisterCatalogueBase &other)=delete
virtual std::unique_ptr< const_RegisterCatalogueImplIterator > getConstIteratorBegin() const =0
Return begin iterator for iterating through the registers in the catalogue.
virtual std::unique_ptr< BackendRegisterCatalogueBase > clone() const =0
Create deep copy of the catalogue.
virtual RegisterInfo getRegister(const RegisterPath &registerPathName) const =0
Get register information for a given full path name.
virtual size_t getNumberOfRegisters() const =0
Get number of registers in the catalogue.
virtual HiddenRange hiddenRegisters() const =0
virtual bool hasRegister(const RegisterPath &registerPathName) const =0
Check if register with the given path name exists.
virtual RegisterPath getDataConsistencyKeyRegisterPath(const std::vector< size_t > &qualifiedAsyncDomainId) const
Return RegisterPath for the register containing the DataConsistencyKey value for the given qualified ...
BackendRegisterCatalogueBase & operator=(BackendRegisterCatalogueBase &&other)=default
virtual std::unique_ptr< const_RegisterCatalogueImplIterator > getConstIteratorEnd() const =0
Return end iterator for iterating through the registers in the catalogue.
Interface for backends to the register catalogue.
std::unique_ptr< const_RegisterCatalogueImplIterator > getConstIteratorEnd() const override
Return end iterator for iterating through the registers in the catalogue.
void modifyRegister(const BackendRegisterInfo &registerInfo)
Replaces the register information for the matching register.
void addRegister(const BackendRegisterInfo &registerInfo)
Add register information to the catalogue.
void removeRegister(const RegisterPath &name)
Remove register as identified by the given name from the catalogue.
void fillFromThis(BackendRegisterCatalogue< BackendRegisterInfo > *target) const
Helper function for clone functions.
RegisterInfo getRegister(const RegisterPath &registerPathName) const final
Note: Implementation internally uses getBackendRegister(), so no need to override.
size_t getNumberOfRegisters() const override
Get number of registers in the catalogue.
const_BackendRegisterCatalogueImplIterator< BackendRegisterInfo > cbegin() const
Return const begin iterators for iterating through the registers in the catalogue.
const_BackendRegisterCatalogueImplIterator< BackendRegisterInfo > end() const
Return const end iterators for iterating through the registers in the catalogue.
std::unique_ptr< BackendRegisterCatalogueBase > clone() const override
Create deep copy of the catalogue.
virtual BackendRegisterInfo getBackendRegister(const RegisterPath &registerPathName) const
Note: Override this function if backend has "hidden" registers which are not added to the map and hen...
bool hasRegister(const RegisterPath &registerPathName) const override
Check if register with the given path name exists.
const_BackendRegisterCatalogueImplIterator< BackendRegisterInfo > begin() const
Return const begin iterators for iterating through the registers in the catalogue.
const_BackendRegisterCatalogueImplIterator< BackendRegisterInfo > cend() const
Return const end iterators for iterating through the registers in the catalogue.
BackendRegisterCatalogueImplIterator< BackendRegisterInfo > end()
Return end iterator for iterating through the registers in the catalogue.
HiddenRange hiddenRegisters() const override
Returns non-owning range of all hidden registers in the catalogue.
std::unique_ptr< const_RegisterCatalogueImplIterator > getConstIteratorBegin() const override
Return begin iterator for iterating through the registers in the catalogue.
BackendRegisterCatalogueImplIterator< BackendRegisterInfo > begin()
Return begin iterator for iterating through the registers in the catalogue.
Non-const iterator for iterating through the registers in the catalogue, used by backend implementati...
BackendRegisterCatalogueImplIterator & operator--()
BackendRegisterCatalogueImplIterator & operator++()
std::vector< BackendRegisterInfo * >::iterator theIterator
bool operator==(const BackendRegisterCatalogueImplIterator &rightHandSide) const
bool operator!=(const BackendRegisterCatalogueImplIterator &rightHandSide) const
DeviceBackend-independent register description.
Const iterator for iterating through the registers in the catalogue.
Class to store a register path name.
Implementation of the catalogue const iterator which is templated to the actual BackendRegisterInfo i...
bool isEqual(const std::unique_ptr< const_RegisterCatalogueImplIterator > &rightHandSide) const override
const_BackendRegisterCatalogueImplIterator & operator++()
const_BackendRegisterCatalogueImplIterator(typename std::vector< BackendRegisterInfo * >::const_iterator it)
std::unique_ptr< const_RegisterCatalogueImplIterator > clone() const override
Create copy of the iterator.
std::vector< BackendRegisterInfo * >::const_iterator theIterator
const_BackendRegisterCatalogueImplIterator & operator--()
bool operator==(const const_BackendRegisterCatalogueImplIterator &rightHandSide) const
bool operator!=(const const_BackendRegisterCatalogueImplIterator &rightHandSide) const
Virtual base class for the catalogue const iterator.
Exception thrown when a logic error has occured.
Definition Exception.h:51
boost::any_range< BackendRegisterInfoBase, boost::forward_traversal_tag, const BackendRegisterInfoBase &, std::ptrdiff_t > HiddenRange
Forward range with type-erasure, used to get a range of hidden registers.