AlexaClientSDK  1.26.0
A cross-platform, modular SDK for interacting with the Alexa Voice Service
Notifier.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 ACSDKNOTIFIER_INTERNAL_NOTIFIER_H_
17 #define ACSDKNOTIFIER_INTERNAL_NOTIFIER_H_
18 
19 #include <algorithm>
20 #include <memory>
21 #include <mutex>
22 #include <vector>
23 
25 
26 namespace alexaClientSDK {
27 namespace acsdkNotifier {
28 
34 template <typename ObserverType>
36 public:
40  Notifier();
41 
44  void addObserver(const std::shared_ptr<ObserverType>& observer) override;
45  void removeObserver(const std::shared_ptr<ObserverType>& observer) override;
46  void addWeakPtrObserver(const std::weak_ptr<ObserverType>& observer) override;
47  void removeWeakPtrObserver(const std::weak_ptr<ObserverType>& observer) override;
48  void notifyObservers(std::function<void(const std::shared_ptr<ObserverType>&)> notify) override;
49  bool notifyObserversInReverse(std::function<void(const std::shared_ptr<ObserverType>&)> notify) override;
50  void setAddObserverFunction(std::function<void(const std::shared_ptr<ObserverType>&)> addObserverFunc) override;
52 
53 private:
60  void cleanupLocked(const std::shared_ptr<ObserverType>& unwanted);
61 
68  bool isAlreadyExistLocked(const std::shared_ptr<ObserverType>& observer);
69 
71  class NotifierObserver {
72  public:
78  explicit NotifierObserver(const std::shared_ptr<ObserverType>& observer);
79 
85  explicit NotifierObserver(const std::weak_ptr<ObserverType>& observer);
86 
92  std::shared_ptr<ObserverType> get() const;
93 
97  void clear();
98 
106  bool isEqualOrExpired(const std::shared_ptr<ObserverType>& observer) const;
107 
108  private:
110  enum class ObserverPointerType {
112  SHARED_PTR,
114  WEAK_PTR
115  };
116 
118  ObserverPointerType m_type;
120  std::shared_ptr<ObserverType> m_sharedPtrObserver;
122  std::weak_ptr<ObserverType> m_weakPtrObserver;
123  };
124 
127  std::recursive_mutex m_mutex;
128 
130  int m_depth;
131 
134  std::vector<NotifierObserver> m_observers;
135 
137  std::function<void(const std::shared_ptr<ObserverType>&)> m_addObserverFunc;
138 };
139 
140 template <typename ObserverType>
141 inline Notifier<ObserverType>::NotifierObserver::NotifierObserver(const std::shared_ptr<ObserverType>& observer) :
142  m_type{ObserverPointerType::SHARED_PTR},
143  m_sharedPtrObserver{observer} {
144 }
145 
146 template <typename ObserverType>
147 inline Notifier<ObserverType>::NotifierObserver::NotifierObserver(const std::weak_ptr<ObserverType>& observer) :
148  m_type{ObserverPointerType::WEAK_PTR},
149  m_weakPtrObserver{observer} {
150 }
151 
152 template <typename ObserverType>
153 inline std::shared_ptr<ObserverType> Notifier<ObserverType>::NotifierObserver::get() const {
154  if (ObserverPointerType::SHARED_PTR == m_type) {
155  return m_sharedPtrObserver;
156  } else {
157  return m_weakPtrObserver.lock();
158  }
159 }
160 
161 template <typename ObserverType>
163  if (ObserverPointerType::SHARED_PTR == m_type) {
164  m_sharedPtrObserver.reset();
165  } else {
166  m_weakPtrObserver.reset();
167  }
168 }
169 
170 template <typename ObserverType>
172  const std::shared_ptr<ObserverType>& observer) const {
173  if (m_type == ObserverPointerType::SHARED_PTR) {
174  return m_sharedPtrObserver == observer;
175  } else {
176  return m_weakPtrObserver.expired() || m_weakPtrObserver.lock() == observer;
177  }
178 }
179 
180 template <typename ObserverType>
181 inline Notifier<ObserverType>::Notifier() : m_depth{0} {
182 }
183 
184 template <typename ObserverType>
185 inline void Notifier<ObserverType>::addObserver(const std::shared_ptr<ObserverType>& observer) {
186  if (!observer) {
187  return;
188  }
189 
190  std::lock_guard<std::recursive_mutex> guard(m_mutex);
191  if (isAlreadyExistLocked(observer)) {
192  return;
193  }
194  m_observers.push_back(NotifierObserver{observer});
195 
196  if (m_addObserverFunc) {
197  m_addObserverFunc(observer);
198  }
199 }
200 
201 template <typename ObserverType>
202 inline void Notifier<ObserverType>::removeObserver(const std::shared_ptr<ObserverType>& observer) {
203  std::lock_guard<std::recursive_mutex> guard(m_mutex);
204  if (m_depth > 0) {
205  for (size_t ix = 0; ix < m_observers.size(); ix++) {
206  auto& notifierObserver = m_observers[ix];
207  if (notifierObserver.get() == observer) {
208  notifierObserver.clear();
209  }
210  }
211  } else {
212  cleanupLocked(observer);
213  }
214 }
215 
216 template <typename ObserverType>
217 inline void Notifier<ObserverType>::addWeakPtrObserver(const std::weak_ptr<ObserverType>& observer) {
218  auto observerSharedPtr = observer.lock();
219  if (!observerSharedPtr) {
220  return;
221  }
222  std::lock_guard<std::recursive_mutex> guard(m_mutex);
223  if (isAlreadyExistLocked(observerSharedPtr)) {
224  return;
225  }
226  m_observers.push_back(NotifierObserver{observer});
227 
228  if (m_addObserverFunc) {
229  m_addObserverFunc(observerSharedPtr);
230  }
231 }
232 
233 template <typename ObserverType>
234 inline void Notifier<ObserverType>::removeWeakPtrObserver(const std::weak_ptr<ObserverType>& observer) {
235  auto observerSharedPtr = observer.lock();
236  if (!observerSharedPtr) {
237  return;
238  }
239  removeObserver(observerSharedPtr);
240 }
241 
242 template <typename ObserverType>
243 inline void Notifier<ObserverType>::notifyObservers(std::function<void(const std::shared_ptr<ObserverType>&)> notify) {
244  std::lock_guard<std::recursive_mutex> guard(m_mutex);
245  m_depth++;
246  for (size_t ix = 0; ix < m_observers.size(); ix++) {
247  const auto& notifierObserver = m_observers[ix];
248  auto observer = notifierObserver.get();
249  if (observer) {
250  notify(observer);
251  }
252  }
253  if (0 == --m_depth) {
254  cleanupLocked(nullptr);
255  }
256 }
257 
258 template <typename ObserverType>
260  std::function<void(const std::shared_ptr<ObserverType>&)> notify) {
261  std::lock_guard<std::recursive_mutex> guard(m_mutex);
262  m_depth++;
263  auto initialSize = m_observers.size();
264  for (auto ix = initialSize; ix-- > 0;) {
265  const auto& notifierObserver = m_observers[ix];
266  auto observer = notifierObserver.get();
267  if (observer) {
268  notify(observer);
269  }
270  }
271  bool result = m_observers.size() == initialSize;
272  if (0 == --m_depth) {
273  cleanupLocked(nullptr);
274  }
275  return result;
276 }
277 
278 template <typename ObserverType>
280  std::function<void(const std::shared_ptr<ObserverType>&)> addObserverFunc) {
281  std::lock_guard<std::recursive_mutex> guard(m_mutex);
282  bool notifyAddedObservers = false;
283  if (!m_addObserverFunc && addObserverFunc) {
284  notifyAddedObservers = true;
285  }
286  m_addObserverFunc = addObserverFunc;
287  if (notifyAddedObservers) {
288  notifyObservers(m_addObserverFunc);
289  }
290 }
291 
292 template <typename ObserverType>
293 inline void Notifier<ObserverType>::cleanupLocked(const std::shared_ptr<ObserverType>& unwanted) {
294  auto matches = [unwanted](NotifierObserver notifierObserver) {
295  return notifierObserver.isEqualOrExpired(unwanted);
296  };
297 
298  m_observers.erase(std::remove_if(m_observers.begin(), m_observers.end(), matches), m_observers.end());
299 }
300 
301 template <typename ObserverType>
302 inline bool Notifier<ObserverType>::isAlreadyExistLocked(const std::shared_ptr<ObserverType>& observer) {
303  for (const auto& existing : m_observers) {
304  if (existing.get() == observer) {
305  return true;
306  }
307  }
308  return false;
309 }
310 
311 } // namespace acsdkNotifier
312 } // namespace alexaClientSDK
313 
314 #endif // ACSDKNOTIFIER_INTERNAL_NOTIFIER_H_
void addWeakPtrObserver(const std::weak_ptr< ObserverType > &observer) override
Definition: Notifier.h:217
void removeWeakPtrObserver(const std::weak_ptr< ObserverType > &observer) override
Definition: Notifier.h:234
void removeObserver(const std::shared_ptr< ObserverType > &observer) override
Definition: Notifier.h:202
bool notifyObserversInReverse(std::function< void(const std::shared_ptr< ObserverType > &)> notify) override
Definition: Notifier.h:259
void setAddObserverFunction(std::function< void(const std::shared_ptr< ObserverType > &)> addObserverFunc) override
Definition: Notifier.h:279
void notifyObservers(std::function< void(const std::shared_ptr< ObserverType > &)> notify) override
Definition: Notifier.h:243
Notifier()
Definition: Notifier.h:181
Whether or not curl logs should be emitted.
Definition: AVSConnectionManager.h:36
static void notifyObservers(const ModeControllerInterface::ModeState &modeState, avsCommon::sdkInterfaces::AlexaStateChangeCauseType cause, const std::list< std::shared_ptr< ModeControllerObserverInterface >> &observers)
Definition: DefaultEndpointModeControllerHandler.cpp:61
void addObserver(const std::shared_ptr< ObserverType > &observer) override
Definition: Notifier.h:185

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