ChimeraTK-DeviceAccess 03.29.00
Loading...
Searching...
No Matches
SharedAccessor.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 "DeviceBackend.h"
8#include "TransferElementID.h"
9#include "VariantUserTypes.h"
10
11#include <mutex>
12
13namespace ChimeraTK::detail {
14
15 using SharedAccessorKey = std::pair<DeviceBackend*, RegisterPath>;
16
20 class SharedAccessors {
21 public:
27 struct TargetSharedState {
28 // Helper name for the variant because the template argument is on NDRegisterAccessor, not the buffer class
29 // itself.
30 template<typename T>
31 using UserBuffer = NDRegisterAccessor<T>::Buffer;
32
33 detail::CountedRecursiveMutex mutex;
34 UserTypeTemplateVariant<UserBuffer> dataBuffer;
35 };
36
43 struct TransferSharedState {
44 size_t instanceCount;
45 };
46
54 template<typename UserType>
55 std::shared_ptr<TargetSharedState> getTargetSharedState(SharedAccessorKey const& key);
56
57 void combineTransferSharedStates(TransferElementID oldId, TransferElementID newId);
58 void addTransferElement(TransferElementID id);
59 void removeTransferElement(TransferElementID id);
60 size_t instanceCount(TransferElementID id);
61
62 protected:
63 std::mutex _mapMutex;
64 // The key to the TargetSharedState is a shared_ptr because we give it out to be stored. Direct pointers/references
65 // to the value objects of the map are not safe against insertions into the map.
66 std::map<SharedAccessorKey, std::shared_ptr<TargetSharedState>> _targetSharedStates;
67 std::map<TransferElementID, TransferSharedState> _transferSharedStates;
68 };
69
70 /********************************************************************************************************************/
71
72 template<typename UserType>
73 std::shared_ptr<SharedAccessors::TargetSharedState> SharedAccessors::getTargetSharedState(
74 SharedAccessorKey const& key) {
75 std::lock_guard<std::mutex> l(_mapMutex); // protect against concurrent map insertion
76 auto& tss = _targetSharedStates[key];
77 if(tss == nullptr) {
78 tss = std::make_shared<TargetSharedState>();
79
80 auto registerInfo = key.first->getRegisterCatalogue().getRegister(key.second);
81 tss->dataBuffer = typename NDRegisterAccessor<UserType>::Buffer(
82 registerInfo.getNumberOfChannels(), registerInfo.getNumberOfElements());
83 }
84 else {
85 // check that requested and existing user type are matching
86 auto _sharedBuffer = std::get_if<typename NDRegisterAccessor<UserType>::Buffer>(&(tss->dataBuffer));
87 if(_sharedBuffer == nullptr) {
88 auto print_variant_type = [](auto&& value) {
89 using T = std::decay_t<decltype(value)>;
90 return boost::core::demangle(typeid(T).name());
91 };
92
93 throw ChimeraTK::logic_error("SubArrayAccessorDecorator for " + key.second + ": Requested TargetUserType '" +
94 boost::core::demangle(typeid(UserType).name()) +
95 "' does not match already existing type. Variant type is '" +
96 std::visit(print_variant_type, tss->dataBuffer) + "'");
97 }
98 }
99
100 return tss;
101 }
102
103} // namespace ChimeraTK::detail
Exception thrown when a logic error has occured.
Definition Exception.h:51