AlexaClientSDK  3.0.0
A cross-platform, modular SDK for interacting with the Alexa Voice Service
InMemoryCommunicationPropertiesHandler.h
Go to the documentation of this file.
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  * http://aws.amazon.com/apache2.0/
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #ifndef ACSDKCOMMUNICATION_INMEMORYCOMMUNICATIONPROPERTIESHANDLER_H_
17 #define ACSDKCOMMUNICATION_INMEMORYCOMMUNICATIONPROPERTIESHANDLER_H_
18 
19 #include <functional>
20 #include <memory>
21 #include <mutex>
22 #include <unordered_map>
23 
30 
31 namespace alexaClientSDK {
32 namespace acsdkCommunication {
33 
37 template <typename T>
38 struct PropertyInfo {
39  std::weak_ptr<acsdkCommunicationInterfaces::CommunicationProperty<T>> property;
40  std::weak_ptr<acsdkCommunicationInterfaces::CommunicationPropertyValidatorInterface<T>> writeValidator;
41 };
46 template <typename T>
49 public:
53  ~InMemoryCommunicationPropertiesHandler() override = default;
54 
60  , public notifier::Notifier<acsdkCommunicationInterfaces::CommunicationPropertyChangeSubscriber<T>> {
61  public:
64  void onCommunicationPropertyChange(const std::string& propertyName, T newValue) override {
65  this->notifyObservers(
67  observer) { observer->onCommunicationPropertyChange(propertyName, newValue); });
68  }
70  };
73  std::shared_ptr<acsdkCommunicationInterfaces::CommunicationProperty<T>> registerProperty(
74  const std::string& propertyName,
75  T initValue,
77  writeValidator = nullptr) override;
78  void deregisterProperty(
79  const std::string& propertyName,
80  const std::shared_ptr<acsdkCommunicationInterfaces::CommunicationProperty<T>>& property) override;
81  bool writeProperty(const std::string& propertyName, T newValue) override;
82 
83  bool readProperty(const std::string& propertyName, T& value) override;
84 
85  bool subscribeToPropertyChangeEvent(
86  const std::string& propertyName,
88  override;
89 
90  bool unsubscribeToPropertyChangeEvent(
91  const std::string& propertyName,
93  override;
95 
96 private:
97  // map of names to property info.
98  std::unordered_map<std::string, PropertyInfo<T>> m_properties;
99  // list of property names to subscribers
100  std::unordered_map<std::string, std::shared_ptr<WeakSubscriptionProxy>> m_subscribers;
101  // mutex to protect the properties.
102  std::mutex m_propertiesMutex;
103 };
104 template <typename T>
105 std::shared_ptr<acsdkCommunicationInterfaces::CommunicationProperty<T>> InMemoryCommunicationPropertiesHandler<T>::
107  const std::string& propertyName,
108  T initValue,
110  writeValidator) {
111  std::unique_lock<std::mutex> lock(m_propertiesMutex);
112  auto it = m_properties.find(propertyName);
113  if (it != m_properties.end()) {
114  if (!it->second.property.expired()) {
116  "InMemoryCommunicationPropertiesHandler", "registerProperty")
117  .m("Property is already Registered")
118  .d("property", propertyName));
119  return nullptr;
120  }
121  // Erase if the property isn't available anymore and reregister
122  m_properties.erase(it);
123  }
125  propertyName, initValue, writeValidator != nullptr);
126  std::weak_ptr<acsdkCommunicationInterfaces::CommunicationProperty<T>> weakProperty =
127  std::weak_ptr<acsdkCommunicationInterfaces::CommunicationProperty<T>>(property);
128  std::weak_ptr<acsdkCommunicationInterfaces::CommunicationPropertyValidatorInterface<T>> weakValidator =
129  std::weak_ptr<acsdkCommunicationInterfaces::CommunicationPropertyValidatorInterface<T>>(writeValidator);
130  PropertyInfo<T> currentInfo{weakProperty, weakValidator};
131  ACSDK_DEBUG(
132  alexaClientSDK::avsCommon::utils::logger::LogEntry("InMemoryCommunicationPropertiesHandler", "registerProperty")
133  .m("Property is Registered")
134  .d("property", propertyName));
135 
136  m_properties.insert({propertyName, currentInfo});
137 
138  auto& subscriberProxy = m_subscribers[propertyName];
139  if (!subscriberProxy) {
140  subscriberProxy = std::make_shared<WeakSubscriptionProxy>();
141  }
142  property->addSubscriber(subscriberProxy);
143 
144  return property;
145 }
146 
147 template <typename T>
149  const std::string& propertyName,
151  std::unique_lock<std::mutex> lock(m_propertiesMutex);
152  auto it = m_properties.find(propertyName);
153  if (it == m_properties.end()) {
155  "InMemoryCommunicationPropertiesHandler", "deregisterProperty")
156  .m("Property is not Registered")
157  .d("property", propertyName));
158  return;
159  }
160  if (it->second.property.lock() != property) {
162  "InMemoryCommunicationPropertiesHandler", "deregisterProperty")
163  .m("Property is registered but can not be matched")
164  .d("property", propertyName));
165  return;
166  }
167  m_properties.erase(it);
168 }
169 
170 template <typename T>
172  std::unique_lock<std::mutex> lock(m_propertiesMutex);
173  auto it = m_properties.find(propertyName);
174  if (it == m_properties.end()) {
176  "InMemoryCommunicationPropertiesHandler", "writeProperty")
177  .m("Property is not Registered")
178  .d("property", propertyName));
179  return false;
180  }
181  auto property = it->second.property.lock();
182  if (!property) {
184  "InMemoryCommunicationPropertiesHandler", "writeProperty")
185  .m("Property has expired")
186  .d("property", propertyName));
187  m_properties.erase(it);
188  return false;
189  }
190  if (!property->isWriteable()) {
192  "InMemoryCommunicationPropertiesHandler", "writeProperty")
193  .m("Property is not writeable")
194  .d("property", propertyName));
195  return false;
196  }
197  auto validator = it->second.writeValidator.lock();
198  if (!validator) {
200  "InMemoryCommunicationPropertiesHandler", "writeProperty")
201  .m("Can't validate property")
202  .d("property", propertyName));
203  return false;
204  }
205  lock.unlock();
206  if (validator->validateWriteRequest(propertyName, newValue)) {
207  property->setValue(newValue);
208  return true;
209  }
210  return false;
211 }
212 template <typename T>
214  std::unique_lock<std::mutex> lock(m_propertiesMutex);
215  auto it = m_properties.find(propertyName);
216  if (it == m_properties.end()) {
217  ACSDK_ERROR(
218  alexaClientSDK::avsCommon::utils::logger::LogEntry("InMemoryCommunicationPropertiesHandler", "readProperty")
219  .m("Property is not Registered")
220  .d("property", propertyName));
221  return false;
222  }
223  auto property = it->second.property.lock();
224  if (!property) {
225  ACSDK_ERROR(
226  alexaClientSDK::avsCommon::utils::logger::LogEntry("InMemoryCommunicationPropertiesHandler", "readProperty")
227  .m("Property has expired")
228  .d("property", propertyName));
229  m_properties.erase(it);
230  return false;
231  }
232  value = property->getValue();
233  return true;
234 }
235 
236 template <typename T>
238  const std::string& propertyName,
240  std::unique_lock<std::mutex> lock(m_propertiesMutex);
241  auto& subscriberProxy = m_subscribers[propertyName];
242  if (!subscriberProxy) {
243  subscriberProxy = std::make_shared<WeakSubscriptionProxy>();
244  }
245  subscriberProxy->addWeakPtrObserver(subscriber);
246  return !subscriber.expired();
247 }
248 
249 template <typename T>
251  const std::string& propertyName,
253  std::unique_lock<std::mutex> lock(m_propertiesMutex);
254  auto& subscriberProxy = m_subscribers[propertyName];
255  if (!subscriberProxy) {
256  subscriberProxy = std::make_shared<WeakSubscriptionProxy>();
257  }
258  subscriberProxy->removeWeakPtrObserver(subscriber);
259  return true;
260 }
261 } // namespace acsdkCommunication
262 } // namespace alexaClientSDK
263 
264 #endif // ACSDKCOMMUNICATION_INMEMORYCOMMUNICATIONPROPERTIESHANDLER_H_
bool readProperty(const std::string &propertyName, T &value) override
}@
Definition: InMemoryCommunicationPropertiesHandler.h:213
std::shared_ptr< acsdkCommunicationInterfaces::CommunicationProperty< T > > registerProperty(const std::string &propertyName, T initValue, const std::shared_ptr< acsdkCommunicationInterfaces::CommunicationPropertyValidatorInterface< T >> &writeValidator=nullptr) override
}@
Definition: InMemoryCommunicationPropertiesHandler.h:106
::std::string string
Definition: gtest-port.h:1097
bool unsubscribeToPropertyChangeEvent(const std::string &propertyName, const std::shared_ptr< acsdkCommunicationInterfaces::CommunicationPropertyChangeSubscriber< T >> &subscriber) override
}@
Definition: InMemoryCommunicationPropertiesHandler.h:250
#define ACSDK_DEBUG(entry)
Definition: Logger.h:454
std::weak_ptr< acsdkCommunicationInterfaces::CommunicationProperty< T > > property
Definition: InMemoryCommunicationPropertiesHandler.h:39
Generic implementation of NotifierInterface.
Definition: Notifier.h:38
Definition: InMemoryCommunicationPropertiesHandler.h:38
std::mutex m
Definition: AlexaPresentationTest.cpp:91
static std::shared_ptr< CommunicationProperty< T > > create(const std::string &name, T initValue, bool writeable)
Definition: CommunicationProperty.h:74
void onCommunicationPropertyChange(const std::string &propertyName, T newValue) override
Definition: InMemoryCommunicationPropertiesHandler.h:64
bool writeProperty(const std::string &propertyName, T newValue) override
}@
Definition: InMemoryCommunicationPropertiesHandler.h:171
std::weak_ptr< acsdkCommunicationInterfaces::CommunicationPropertyValidatorInterface< T > > writeValidator
Definition: InMemoryCommunicationPropertiesHandler.h:40
#define ACSDK_ERROR(entry)
Definition: Logger.h:481
void deregisterProperty(const std::string &propertyName, const std::shared_ptr< acsdkCommunicationInterfaces::CommunicationProperty< T >> &property) override
}@
Definition: InMemoryCommunicationPropertiesHandler.h:148
Definition: InMemoryCommunicationPropertiesHandler.h:47
Whether or not curl logs should be emitted.
Definition: AVSConnectionManager.h:36
bool subscribeToPropertyChangeEvent(const std::string &propertyName, const std::weak_ptr< acsdkCommunicationInterfaces::CommunicationPropertyChangeSubscriber< T >> &subscriber) override
}@
Definition: InMemoryCommunicationPropertiesHandler.h:237
LogEntry is used to compile the log entry text to log via Logger.
Definition: LogEntry.h:33

AlexaClientSDK 3.0.0 - Copyright 2016-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0