ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
DomainImpl.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
5#include "../VersionNumber.h"
7#include "Domain.h"
8#include "SubDomain.h"
9
10#include <functional>
11
12namespace ChimeraTK::async {
13
14 template<typename BackendDataType>
15 class DomainImpl : public Domain {
16 public:
17 DomainImpl(boost::shared_ptr<DeviceBackend> backend, size_t domainId) : _backend(backend), _id(domainId) {}
18
37 VersionNumber distribute(BackendDataType data, VersionNumber version = VersionNumber{nullptr});
38
50 VersionNumber activate(BackendDataType data, VersionNumber version = VersionNumber{nullptr});
51
52 void deactivate() override;
53 void sendException(const std::exception_ptr& e) noexcept override;
54
55 template<typename UserDataType>
56 boost::shared_ptr<AsyncNDRegisterAccessor<UserDataType>> subscribe(
57 RegisterPath name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags);
58
59 protected:
60 // Everything in this class is protected by the mutex from the Domain base class.
61 boost::weak_ptr<SubDomain<BackendDataType>> _subDomain;
62
63 boost::shared_ptr<DeviceBackend> _backend;
64 size_t _id;
65
66 // Data to resolve a race condition (see distribute and activate)
67 BackendDataType _notDistributedData;
70 };
71
72 /********************************************************************************************************************/
73
74 template<typename BackendDataType>
76 std::lock_guard l(_mutex);
77 // everything incl. potential creation of a new version number must happen under the lock
78 if(version == VersionNumber(nullptr)) {
79 version = {};
80 }
81
82 if(!_isActive) {
83 // Store the data. We might need it later if the data in activate is older due to a race condition.
84 _notDistributedData = data;
85 _notDistributedVersion = version;
86 return VersionNumber{nullptr};
87 }
88
89 if(version < _activationVersion) {
90 return VersionNumber{nullptr};
91 }
92
93 auto subDomain = _subDomain.lock();
94 if(!subDomain) {
95 return VersionNumber{nullptr};
96 }
97
98 subDomain->distribute(data, version);
99 return version;
100 }
101
102 /********************************************************************************************************************/
103
104 template<typename BackendDataType>
106 std::lock_guard l(_mutex);
107 // everything incl. potential creation of a new version number must happen under the lock
108 if(_isActive) {
109 return VersionNumber(nullptr);
110 }
111
112 if(version == VersionNumber(nullptr)) {
113 version = {};
114 }
115
116 _isActive = true;
117
118 auto subDomain = _subDomain.lock();
119 if(!subDomain) {
120 return VersionNumber{nullptr};
121 }
122
123 if(version >= _notDistributedVersion) {
124 subDomain->activate(data, version);
125 _activationVersion = version;
126 }
127 else {
128 // Due to a race condition, it has been tried to distribute newer data before activate was called.
129 subDomain->activate(_notDistributedData, _notDistributedVersion);
130 _activationVersion = _notDistributedVersion;
131 }
132 return _activationVersion;
133 }
134
135 /********************************************************************************************************************/
136
137 template<typename BackendDataType>
139 std::lock_guard l(_mutex);
140
141 _isActive = false;
142 }
143
144 /********************************************************************************************************************/
145
146 template<typename BackendDataType>
147 void DomainImpl<BackendDataType>::sendException(const std::exception_ptr& e) noexcept {
148 std::lock_guard l(_mutex);
149
150 if(!_isActive) {
151 // don't send exceptions if async read is off
152 return;
153 }
154
155 _isActive = false;
156 auto subDomain = _subDomain.lock();
157 if(!subDomain) {
158 return;
159 }
160
161 subDomain->sendException(e);
162 }
163
164 /********************************************************************************************************************/
165
166 template<typename BackendDataType>
167 template<typename UserDataType>
168 boost::shared_ptr<AsyncNDRegisterAccessor<UserDataType>> DomainImpl<BackendDataType>::subscribe(
169 RegisterPath name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
170 std::lock_guard l(_mutex);
171
172 auto subDomain = _subDomain.lock();
173 if(!subDomain) {
174 subDomain = boost::make_shared<SubDomain<BackendDataType>>(
175 _backend, std::vector<size_t>({_id}), nullptr, shared_from_this());
176 _subDomain = subDomain;
177 }
178
179 return subDomain->template subscribe<UserDataType>(name, numberOfWords, wordOffsetInRegister, flags);
180 }
181
182} // namespace ChimeraTK::async
Set of AccessMode flags with additional functionality for an easier handling.
Definition AccessMode.h:48
Class to store a register path name.
Class for generating and holding version numbers without exposing a numeric representation.
The Domain is the thread-safe entry point for each distribution tree.
Definition Domain.h:25
VersionNumber _notDistributedVersion
Definition DomainImpl.h:68
void sendException(const std::exception_ptr &e) noexcept override
Definition DomainImpl.h:147
VersionNumber activate(BackendDataType data, VersionNumber version=VersionNumber{nullptr})
Activate and distribute the initial value.
Definition DomainImpl.h:105
boost::weak_ptr< SubDomain< BackendDataType > > _subDomain
Definition DomainImpl.h:61
VersionNumber distribute(BackendDataType data, VersionNumber version=VersionNumber{nullptr})
Distribute the data via the associated distribution tree.
Definition DomainImpl.h:75
VersionNumber _activationVersion
Definition DomainImpl.h:69
DomainImpl(boost::shared_ptr< DeviceBackend > backend, size_t domainId)
Definition DomainImpl.h:17
boost::shared_ptr< AsyncNDRegisterAccessor< UserDataType > > subscribe(RegisterPath name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
Definition DomainImpl.h:168
BackendDataType _notDistributedData
Definition DomainImpl.h:67
boost::shared_ptr< DeviceBackend > _backend
Definition DomainImpl.h:63