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