AlexaClientSDK  3.0.0
A cross-platform, modular SDK for interacting with the Alexa Voice Service
CookBook_imp.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 ACSDKMANUFACTORY_INTERNAL_COOKBOOK_IMP_H_
17 #define ACSDKMANUFACTORY_INTERNAL_COOKBOOK_IMP_H_
18 
19 #include <iostream>
20 #include <list>
21 #include <map>
22 #include <memory>
23 #include <set>
24 #include <stack>
25 #include <tuple>
26 
28 
35 
36 namespace alexaClientSDK {
37 namespace acsdkManufactory {
38 namespace internal {
39 
40 template <typename Type, typename... Dependencies>
41 inline CookBook& CookBook::addUniqueFactory(std::function<std::unique_ptr<Type>(Dependencies...)> function) {
42  if (!checkIsValid(__func__)) {
43  return *this;
44  }
45 
46  using ResultType = std::unique_ptr<Type>;
47  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
48  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
49 
50  auto newRecipe = std::make_shared<FunctionRecipe>(
51  reinterpret_cast<void*>(funcPtr),
52  AbstractRecipe::CachedInstanceLifecycle::UNIQUE,
53  dependencies,
54  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
55  produceFromUniqueFunctionRecipe<Type, Dependencies...>),
56  static_cast<void (*)(void*)>(deleteFunctionForUniqueRecipe),
57  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
58 
59  auto type = avsCommon::utils::getTypeIndex<ResultType>();
60  if (!addRecipe(type, newRecipe)) {
61  markInvalid("addUniqueFactoryFailed", "non-isEquivalent recipe ", type.getName());
62  }
63 
64  return *this;
65 }
66 
67 template <typename Type, typename... Dependencies>
68 inline CookBook& CookBook::addUniqueFactory(std::unique_ptr<Type> (*factory)(Dependencies...)) {
69  if (!checkIsValid(__func__)) {
70  return *this;
71  }
72 
73  using ResultType = std::unique_ptr<Type>;
74  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
75 
76  auto newRecipe = std::make_shared<FactoryRecipe>(
77  reinterpret_cast<void* (*)()>(factory),
78  AbstractRecipe::CachedInstanceLifecycle::UNIQUE,
79  dependencies,
80  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
81  produceFromUniqueFactoryRecipe<Type, Dependencies...>),
82  static_cast<void (*)(void*)>(deleteFunctionForUniqueRecipe));
83 
84  auto type = avsCommon::utils::getTypeIndex<ResultType>();
85  if (!addRecipe(type, newRecipe)) {
86  markInvalid("addUniqueFactoryFailed", "non-isEquivalent recipe ", type.getName());
87  }
88 
89  return *this;
90 }
91 
92 template <typename Type, typename... Dependencies>
93 inline CookBook& CookBook::addPrimaryFactory(std::function<std::shared_ptr<Type>(Dependencies...)> function) {
94  if (!checkIsValid(__func__)) {
95  return *this;
96  }
97 
98  using ResultType = std::shared_ptr<Type>;
99  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
100  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
101 
102  auto newRecipe = std::make_shared<FunctionRecipe>(
103  reinterpret_cast<void*>(funcPtr),
104  AbstractRecipe::CachedInstanceLifecycle::PRIMARY,
105  dependencies,
106  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
107  produceFromSharedFunctionRecipe<Type, Dependencies...>),
108  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
109  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
110 
111  auto type = avsCommon::utils::getTypeIndex<ResultType>();
112  if (!addRecipe(type, newRecipe)) {
113  markInvalid("addPrimaryFactoryFailed", "non-isEquivalent recipe ", type.getName());
114  }
115 
116  m_primaryGets->append<ResultType>(
117  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
118 
119  return *this;
120 }
121 
122 template <typename Annotation, typename Type, typename... Dependencies>
123 inline CookBook& CookBook::addPrimaryFactory(std::function<Annotated<Annotation, Type>(Dependencies...)> function) {
124  if (!checkIsValid(__func__)) {
125  return *this;
126  }
127 
128  using ResultType = Annotated<Annotation, Type>;
129  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
130  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
131 
132  auto newRecipe = std::make_shared<FunctionRecipe>(
133  reinterpret_cast<void*>(funcPtr),
134  AbstractRecipe::CachedInstanceLifecycle::PRIMARY,
135  dependencies,
136  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
137  produceFromAnnotatedSharedFunctionRecipe<Type, Annotation, Dependencies...>),
138  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
139  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
140 
141  auto type = avsCommon::utils::getTypeIndex<ResultType>();
142  if (!addRecipe(type, newRecipe)) {
143  markInvalid("addPrimaryFactoryFailed", "non-isEquivalent recipe ", type.getName());
144  }
145 
146  m_primaryGets->append<ResultType>(
147  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
148 
149  return *this;
150 }
151 
152 template <typename Type, typename... Dependencies>
153 inline CookBook& CookBook::addPrimaryFactory(std::shared_ptr<Type> (*factory)(Dependencies...)) {
154  if (!checkIsValid(__func__)) {
155  return *this;
156  }
157 
158  using ResultType = std::shared_ptr<Type>;
159  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
160 
161  auto newRecipe = std::make_shared<FactoryRecipe>(
162  reinterpret_cast<void* (*)()>(factory),
163  AbstractRecipe::CachedInstanceLifecycle::PRIMARY,
164  dependencies,
165  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
166  produceFromSharedFactoryRecipe<Type, Dependencies...>),
167  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
168 
169  auto type = avsCommon::utils::getTypeIndex<ResultType>();
170  if (!addRecipe(type, newRecipe)) {
171  markInvalid("addPrimaryFactoryFailed", "non-isEquivalent recipe ", type.getName());
172  }
173 
174  m_primaryGets->append<ResultType>(
175  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
176 
177  return *this;
178 }
179 
180 template <typename Annotation, typename Type, typename... Dependencies>
182  if (!checkIsValid(__func__)) {
183  return *this;
184  }
185 
186  using ResultType = Annotated<Annotation, Type>;
187  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
188 
189  auto newRecipe = std::make_shared<FactoryRecipe>(
190  reinterpret_cast<void* (*)()>(factory),
191  AbstractRecipe::CachedInstanceLifecycle::PRIMARY,
192  dependencies,
193  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
194  produceFromAnnotatedSharedFactoryRecipe<Type, Annotation, Dependencies...>),
195  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
196 
197  auto type = avsCommon::utils::getTypeIndex<ResultType>();
198  if (!addRecipe(type, newRecipe)) {
199  markInvalid("addPrimaryFactoryFailed", "non-isEquivalent recipe ", type.getName());
200  }
201 
202  m_primaryGets->append<ResultType>(
203  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
204 
205  return *this;
206 }
207 
208 template <typename Type, typename... Dependencies>
209 inline CookBook& CookBook::addRequiredFactory(std::function<std::shared_ptr<Type>(Dependencies...)> function) {
210  if (!checkIsValid(__func__)) {
211  return *this;
212  }
213 
214  using ResultType = std::shared_ptr<Type>;
215  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
216  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
217 
218  auto newRecipe = std::make_shared<FunctionRecipe>(
219  reinterpret_cast<void*>(funcPtr),
220  AbstractRecipe::CachedInstanceLifecycle::REQUIRED,
221  dependencies,
222  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
223  produceFromSharedFunctionRecipe<Type, Dependencies...>),
224  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
225  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
226 
227  auto type = avsCommon::utils::getTypeIndex<ResultType>();
228  if (!addRecipe(type, newRecipe)) {
229  markInvalid("addRequiredFactoryFailed", "non-isEquivalent recipe ", type.getName());
230  }
231 
232  m_requiredGets->append<ResultType>(
233  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
234 
235  return *this;
236 }
237 
238 template <typename Annotation, typename Type, typename... Dependencies>
239 inline CookBook& CookBook::addRequiredFactory(std::function<Annotated<Annotation, Type>(Dependencies...)> function) {
240  if (!checkIsValid(__func__)) {
241  return *this;
242  }
243 
244  using ResultType = Annotated<Annotation, Type>;
245  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
246  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
247 
248  auto newRecipe = std::make_shared<FunctionRecipe>(
249  reinterpret_cast<void*>(funcPtr),
250  AbstractRecipe::CachedInstanceLifecycle::REQUIRED,
251  dependencies,
252  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
253  produceFromAnnotatedSharedFunctionRecipe<Type, Annotation, Dependencies...>),
254  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
255  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
256 
257  auto type = avsCommon::utils::getTypeIndex<ResultType>();
258  if (!addRecipe(type, newRecipe)) {
259  markInvalid("addRequiredFactoryFailed", "non-isEquivalent recipe ", type.getName());
260  }
261 
262  m_requiredGets->append<ResultType>(
263  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
264 
265  return *this;
266 }
267 
268 template <typename Type, typename... Dependencies>
269 inline CookBook& CookBook::addRequiredFactory(std::shared_ptr<Type> (*factory)(Dependencies...)) {
270  if (!checkIsValid(__func__)) {
271  return *this;
272  }
273 
274  using ResultType = std::shared_ptr<Type>;
275  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
276 
277  auto newRecipe = std::make_shared<FactoryRecipe>(
278  reinterpret_cast<void* (*)()>(factory),
279  AbstractRecipe::CachedInstanceLifecycle::REQUIRED,
280  dependencies,
281  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
282  produceFromSharedFactoryRecipe<Type, Dependencies...>),
283  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
284 
285  auto type = avsCommon::utils::getTypeIndex<ResultType>();
286  if (!addRecipe(type, newRecipe)) {
287  markInvalid("addRequiredFactoryFailed", "non-isEquivalent recipe ", type.getName());
288  }
289 
290  m_requiredGets->append<ResultType>(
291  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
292 
293  return *this;
294 }
295 
296 template <typename Annotation, typename Type, typename... Dependencies>
298  if (!checkIsValid(__func__)) {
299  return *this;
300  }
301 
302  using ResultType = Annotated<Annotation, Type>;
303  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
304 
305  auto newRecipe = std::make_shared<FactoryRecipe>(
306  reinterpret_cast<void* (*)()>(factory),
307  AbstractRecipe::CachedInstanceLifecycle::REQUIRED,
308  dependencies,
309  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
310  produceFromAnnotatedSharedFactoryRecipe<Type, Annotation, Dependencies...>),
311  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
312 
313  auto type = avsCommon::utils::getTypeIndex<ResultType>();
314  if (!addRecipe(type, newRecipe)) {
315  markInvalid("addRequiredFactoryFailed", "non-isEquivalent recipe ", type.getName());
316  }
317 
318  m_requiredGets->append<ResultType>(
319  [](RuntimeManufactory& runtimeManufactory) { return static_cast<bool>(runtimeManufactory.get<ResultType>()); });
320 
321  return *this;
322 }
323 
324 template <typename Type, typename... Dependencies>
325 inline CookBook& CookBook::addRetainedFactory(std::function<std::shared_ptr<Type>(Dependencies...)> function) {
326  if (!checkIsValid(__func__)) {
327  return *this;
328  }
329 
330  using ResultType = std::shared_ptr<Type>;
331  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
332  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
333 
334  auto newRecipe = std::make_shared<FunctionRecipe>(
335  reinterpret_cast<void*>(funcPtr),
336  AbstractRecipe::CachedInstanceLifecycle::RETAINED,
337  dependencies,
338  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
339  produceFromSharedFunctionRecipe<Type, Dependencies...>),
340  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
341  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
342 
343  auto type = avsCommon::utils::getTypeIndex<ResultType>();
344  if (!addRecipe(type, newRecipe)) {
345  markInvalid("addRetainedFactoryFailed", "non-isEquivalent recipe ", type.getName());
346  }
347 
348  return *this;
349 }
350 
351 template <typename Annotation, typename Type, typename... Dependencies>
352 inline CookBook& CookBook::addRetainedFactory(std::function<Annotated<Annotation, Type>(Dependencies...)> function) {
353  if (!checkIsValid(__func__)) {
354  return *this;
355  }
356 
357  using ResultType = Annotated<Annotation, Type>;
358  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
359  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
360 
361  auto newRecipe = std::make_shared<FunctionRecipe>(
362  reinterpret_cast<void*>(funcPtr),
363  AbstractRecipe::CachedInstanceLifecycle::RETAINED,
364  dependencies,
365  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
366  produceFromAnnotatedSharedFunctionRecipe<Type, Annotation, Dependencies...>),
367  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
368  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
369 
370  auto type = avsCommon::utils::getTypeIndex<ResultType>();
371  if (!addRecipe(type, newRecipe)) {
372  markInvalid("addRetainedFactoryFailed", "non-isEquivalent recipe ", type.getName());
373  }
374 
375  return *this;
376 }
377 
378 template <typename Type, typename... Dependencies>
379 inline CookBook& CookBook::addRetainedFactory(std::shared_ptr<Type> (*factory)(Dependencies...)) {
380  if (!checkIsValid(__func__)) {
381  return *this;
382  }
383 
384  using ResultType = std::shared_ptr<Type>;
385  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
386 
387  auto newRecipe = std::make_shared<FactoryRecipe>(
388  reinterpret_cast<void* (*)()>(factory),
389  AbstractRecipe::CachedInstanceLifecycle::RETAINED,
390  dependencies,
391  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
392  produceFromSharedFactoryRecipe<Type, Dependencies...>),
393  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
394 
395  auto type = avsCommon::utils::getTypeIndex<ResultType>();
396  if (!addRecipe(type, newRecipe)) {
397  markInvalid("addRetainedFactoryFailed", "non-isEquivalent recipe ", type.getName());
398  }
399 
400  return *this;
401 }
402 
403 template <typename Annotation, typename Type, typename... Dependencies>
405  if (!checkIsValid(__func__)) {
406  return *this;
407  }
408 
409  using ResultType = Annotated<Annotation, Type>;
410  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
411 
412  auto newRecipe = std::make_shared<FactoryRecipe>(
413  reinterpret_cast<void* (*)()>(factory),
414  AbstractRecipe::CachedInstanceLifecycle::RETAINED,
415  dependencies,
416  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
417  produceFromAnnotatedSharedFactoryRecipe<Type, Annotation, Dependencies...>),
418  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
419 
420  auto type = avsCommon::utils::getTypeIndex<ResultType>();
421  if (!addRecipe(type, newRecipe)) {
422  markInvalid("addRetainedFactoryFailed", "non-isEquivalent recipe ", type.getName());
423  }
424 
425  return *this;
426 }
427 
428 template <typename Type, typename... Dependencies>
429 inline CookBook& CookBook::addUnloadableFactory(std::function<std::shared_ptr<Type>(Dependencies...)> function) {
430  if (!checkIsValid(__func__)) {
431  return *this;
432  }
433 
434  using ResultType = std::shared_ptr<Type>;
435  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
436  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
437 
438  auto newRecipe = std::make_shared<FunctionRecipe>(
439  reinterpret_cast<void*>(funcPtr),
440  AbstractRecipe::CachedInstanceLifecycle::UNLOADABLE,
441  dependencies,
442  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
443  produceFromSharedFunctionRecipe<Type, Dependencies...>),
444  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
445  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
446 
447  auto type = avsCommon::utils::getTypeIndex<ResultType>();
448  if (!addRecipe(type, newRecipe)) {
449  markInvalid("addUnloadableFactoryFailed", "non-isEquivalent recipe ", type.getName());
450  }
451 
452  return *this;
453 }
454 
455 template <typename Annotation, typename Type, typename... Dependencies>
456 inline CookBook& CookBook::addUnloadableFactory(std::function<Annotated<Annotation, Type>(Dependencies...)> function) {
457  if (!checkIsValid(__func__)) {
458  return *this;
459  }
460 
461  using ResultType = Annotated<Annotation, Type>;
462  auto funcPtr = new std::function<ResultType(Dependencies...)>(function);
463  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
464 
465  auto newRecipe = std::make_shared<FunctionRecipe>(
466  reinterpret_cast<void*>(funcPtr),
467  AbstractRecipe::CachedInstanceLifecycle::UNLOADABLE,
468  dependencies,
469  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
470  produceFromAnnotatedSharedFunctionRecipe<Type, Annotation, Dependencies...>),
471  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>),
472  static_cast<void (*)(void*)>(deleteFunctionForFunctionRecipeFunction<ResultType, Dependencies...>));
473 
474  auto type = avsCommon::utils::getTypeIndex<ResultType>();
475  if (!addRecipe(type, newRecipe)) {
476  markInvalid("addUnloadableFactoryFailed", "non-isEquivalent recipe ", type.getName());
477  }
478 
479  return *this;
480 }
481 
482 template <typename Type, typename... Dependencies>
483 inline CookBook& CookBook::addUnloadableFactory(std::shared_ptr<Type> (*factory)(Dependencies...)) {
484  if (!checkIsValid(__func__)) {
485  return *this;
486  }
487 
488  using ResultType = std::shared_ptr<Type>;
489  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
490 
491  auto newRecipe = std::make_shared<FactoryRecipe>(
492  reinterpret_cast<void* (*)()>(factory),
493  AbstractRecipe::CachedInstanceLifecycle::UNLOADABLE,
494  dependencies,
495  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
496  produceFromSharedFactoryRecipe<Type, Dependencies...>),
497  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
498 
499  auto type = avsCommon::utils::getTypeIndex<ResultType>();
500  if (!addRecipe(type, newRecipe)) {
501  markInvalid("addUnloadableFactoryFailed", "non-isEquivalent recipe ", type.getName());
502  }
503 
504  return *this;
505 }
506 
507 template <typename Annotation, typename Type, typename... Dependencies>
509  if (!checkIsValid(__func__)) {
510  return *this;
511  }
512 
513  using ResultType = Annotated<Annotation, Type>;
514  std::vector<avsCommon::utils::TypeIndex> dependencies = {avsCommon::utils::getTypeIndex<Dependencies>()...};
515 
516  auto newRecipe = std::make_shared<FactoryRecipe>(
517  reinterpret_cast<void* (*)()>(factory),
518  AbstractRecipe::CachedInstanceLifecycle::UNLOADABLE,
519  dependencies,
520  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(
521  produceFromAnnotatedSharedFactoryRecipe<Type, Annotation, Dependencies...>),
522  static_cast<void (*)(void*)>(deleteFunctionForSharedRecipe<Type>));
523 
524  auto type = avsCommon::utils::getTypeIndex<ResultType>();
525  if (!addRecipe(type, newRecipe)) {
526  markInvalid("addUnloadableFactoryFailed", "non-isEquivalent recipe ", type.getName());
527  }
528 
529  return *this;
530 }
531 
532 template <typename Type>
533 inline CookBook& CookBook::addInstance(const Type& instance) {
534  if (!checkIsValid(__func__)) {
535  return *this;
536  }
537 
538  auto newRecipe = std::make_shared<InstanceRecipe>(
539  instance,
540  static_cast<void* (*)(std::shared_ptr<AbstractRecipe>, RuntimeManufactory&, void*)>(produceFromInstanceRecipe),
541  static_cast<void (*)(void*)>(deleteFunctionForInstanceRecipe));
542 
543  auto type = avsCommon::utils::getTypeIndex<Type>();
544  if (!addInstance(type, newRecipe)) {
545  markInvalid("addInstanceFailed", "non-isEquivalent instance ", type.getName());
546  }
547 
548  return *this;
549 }
550 
551 inline bool CookBook::addInstance(
553  const std::shared_ptr<AbstractRecipe>& newInstanceRecipe) {
554  auto& RecipePtr = m_recipes[type];
555  if (RecipePtr) {
556  if (!RecipePtr->isEquivalent(newInstanceRecipe)) {
557  return false;
558  }
559  } else {
560  RecipePtr = newInstanceRecipe;
561  }
562 
563  return true;
564 }
565 
566 inline bool CookBook::addRecipe(avsCommon::utils::TypeIndex type, const std::shared_ptr<AbstractRecipe>& newRecipe) {
567  auto& RecipePtr = m_recipes[type];
568  if (RecipePtr) {
570 #ifndef _WIN32
571  if (!RecipePtr->isEquivalent(newRecipe)) {
572  return false;
573  }
574 #endif
575  } else {
576  RecipePtr = newRecipe;
577  }
578 
579  return true;
580 }
581 
582 inline CookBook& CookBook::addCookBook(const CookBook& cookBook) {
583  if (!checkIsValid(__func__)) {
584  return *this;
585  }
586 
587  if (!cookBook.checkIsValid(__func__)) {
588  markInvalid("addCookBookFailed", "invalid component");
589  return *this;
590  }
591 
592  // Merge component's recipes in to this component's recipes.
593 
594  for (auto item : cookBook.m_recipes) {
595  auto it = m_recipes.find(item.first);
596  if (it != m_recipes.end()) {
597  if (!it->second->isEquivalent(item.second)) {
598  markInvalid("addCookBookFailed", "isEquivalentFailed");
599  return *this;
600  }
601  } else {
602  m_recipes.insert(item);
603  }
604  }
605 
606  m_primaryGets->append(cookBook.m_primaryGets);
607  m_requiredGets->append(cookBook.m_requiredGets);
608 
609  return *this;
610 };
611 
614  for (auto getFcn : *m_primaryGets) {
615  if (!getFcn || !getFcn(runtimeManufactory)) {
616  return false;
617  }
618  }
619 
620  for (auto getFcn : *m_requiredGets) {
621  if (!getFcn || !getFcn(runtimeManufactory)) {
622  return false;
623  }
624  }
625 
626  return true;
627 }
628 
629 template <typename Type>
630 inline std::unique_ptr<Type> CookBook::createUniquePointer(RuntimeManufactory& runtimeManufactory) {
631  if (!checkIsValid(__func__)) {
632  return std::unique_ptr<Type>();
633  }
634 
635  auto type = avsCommon::utils::getTypeIndex<std::unique_ptr<Type>>();
636  auto it = m_recipes.find(type);
637  if (it != m_recipes.end()) {
638  if (it->second) {
639  auto recipe = it->second;
640  auto createUniquePointer = recipe->getProduceInstanceFunction();
641 
645 
647  auto temporaryPointerToUniquePointerOnHeap =
648  static_cast<std::unique_ptr<Type>*>(createUniquePointer(recipe, runtimeManufactory, nullptr));
649 
652  auto uniquePointerToReturn = std::move(*temporaryPointerToUniquePointerOnHeap);
653 
655  delete temporaryPointerToUniquePointerOnHeap;
656 
657  return uniquePointerToReturn;
658 
659  } else {
660  markInvalid("createUniquePointerFailed", "null Recipe for type: ", type.getName());
661  return std::unique_ptr<Type>();
662  }
663  }
664 
665  markInvalid("createUniquePointerFailed", "no Recipe for type", type.getName());
666  return std::unique_ptr<Type>();
667 }
668 
669 template <typename Type>
670 inline std::unique_ptr<AbstractPointerCache> CookBook::createPointerCache() {
671  if (!checkIsValid(__func__)) {
672  return std::unique_ptr<SharedPointerCache>();
673  }
674 
675  auto type = avsCommon::utils::getTypeIndex<Type>();
676  auto it = m_recipes.find(type);
677  if (it != m_recipes.end()) {
678  if (it->second) {
679  auto recipe = it->second;
680  if (AbstractRecipe::CachedInstanceLifecycle::UNLOADABLE == recipe->getLifecycle()) {
681  return std::unique_ptr<WeakPointerCache>(new WeakPointerCache(recipe));
682  }
683  return std::unique_ptr<SharedPointerCache>(new SharedPointerCache(recipe));
684  } else {
685  markInvalid("createPointerCacheFailed", "null Recipe for type: ", type.getName());
686  return std::unique_ptr<SharedPointerCache>();
687  }
688  }
689 
690  markInvalid("createPointerCacheFailed", "no Recipe for type", type.getName());
691  return std::unique_ptr<SharedPointerCache>();
692 }
693 
695  m_isValid{true},
696  m_primaryGets{std::make_shared<GetWrapperCollection>()},
697  m_requiredGets{std::make_shared<GetWrapperCollection>()} {
698 }
699 
701  if (!checkIsValid(__func__)) {
702  return false;
703  }
704 
705  return checkForCyclicDependencies();
706 }
707 
708 inline bool CookBook::checkIsValid(const char* functionName) const {
709  if (!m_isValid) {
711  avsCommon::utils::logger::LogEntry(getLoggerTag(), "checkIsValidFailed").d("function", functionName));
712  }
713  return m_isValid;
714 }
715 
716 inline void CookBook::markInvalid(const std::string& event, const std::string& reason, const std::string& type) {
717  m_isValid = false;
719  avsCommon::utils::logger::LogEntry(getLoggerTag(), event).d("reason", reason).d("type", type));
720 }
721 
722 template <typename Type, typename... Dependencies>
723 inline Type CookBook::invokeWithDependencies(
724  RuntimeManufactory& runtimeManufactory,
725  std::function<Type(Dependencies...)> function) {
726  using FcnType = typename std::function<Type(Dependencies...)>;
727  return CookBook::template innerInvokeWithDependencies<Type, FcnType, Dependencies...>(
728  function, runtimeManufactory.get<RemoveCvref_t<Dependencies>>()...);
729 };
730 
731 template <typename Type, typename FunctionType, typename... Dependencies>
732 inline Type CookBook::innerInvokeWithDependencies(FunctionType function, Dependencies... dependencies) {
733  return function(std::move(dependencies)...);
734 }
735 
736 template <typename Type, typename... Dependencies>
737 inline void* CookBook::produceFromSharedFactoryRecipe(
738  std::shared_ptr<AbstractRecipe> recipe,
739  RuntimeManufactory& runtimeManufactory,
740  void* cachedInstance) {
741  if (cachedInstance) {
742  return cachedInstance;
743  }
744 
745  auto factoryRecipe = reinterpret_cast<FactoryRecipe*>(recipe.get());
746  auto factory = reinterpret_cast<std::shared_ptr<Type> (*)(Dependencies...)>(factoryRecipe->getFactory());
747 
748  InstanceGetter<std::shared_ptr<Type>, Dependencies...> getter = [factory](Dependencies... dependencies) {
749  return factory(std::move(dependencies)...);
750  };
751 
752  return new std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, getter));
753 }
754 
755 template <typename Type, typename Annotation, typename... Dependencies>
756 inline void* CookBook::produceFromAnnotatedSharedFactoryRecipe(
757  std::shared_ptr<AbstractRecipe> recipe,
758  RuntimeManufactory& runtimeManufactory,
759  void* cachedInstance) {
760  if (cachedInstance) {
761  return cachedInstance;
762  }
763 
764  auto factoryRecipe = reinterpret_cast<FactoryRecipe*>(recipe.get());
765  auto factory = reinterpret_cast<Annotated<Annotation, Type> (*)(Dependencies...)>(factoryRecipe->getFactory());
766 
767  InstanceGetter<std::shared_ptr<Type>, Dependencies...> getter = [factory](Dependencies... dependencies) {
768  return factory(std::move(dependencies)...);
769  };
770 
771  return new std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, getter));
772 }
773 
774 template <typename Type, typename... Dependencies>
775 inline void* CookBook::produceFromSharedFunctionRecipe(
776  std::shared_ptr<AbstractRecipe> recipe,
777  RuntimeManufactory& runtimeManufactory,
778  void* cachedInstance) {
779  if (cachedInstance) {
780  return cachedInstance;
781  }
782  auto functionRecipe = reinterpret_cast<FunctionRecipe*>(recipe.get());
783  auto function = *static_cast<std::function<std::shared_ptr<Type>(Dependencies...)>*>(functionRecipe->getFunction());
784 
785  return new std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, function));
786 }
787 
788 template <typename Type, typename Annotation, typename... Dependencies>
789 inline void* CookBook::produceFromAnnotatedSharedFunctionRecipe(
790  std::shared_ptr<AbstractRecipe> recipe,
791  RuntimeManufactory& runtimeManufactory,
792  void* cachedInstance) {
793  if (cachedInstance) {
794  return cachedInstance;
795  }
796  auto functionRecipe = reinterpret_cast<FunctionRecipe*>(recipe.get());
797  auto function =
798  *static_cast<std::function<Annotated<Annotation, Type>(Dependencies...)>*>(functionRecipe->getFunction());
799 
800  auto temp = std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, function));
801  return new std::shared_ptr<void>(temp);
802 }
803 
804 template <typename Type, typename... Dependencies>
805 inline void* CookBook::produceFromWeakFactoryRecipe(
806  std::shared_ptr<AbstractRecipe> recipe,
807  RuntimeManufactory& runtimeManufactory,
808  void* cachedInstance) {
809  auto factoryRecipe = reinterpret_cast<FactoryRecipe*>(recipe.get());
810  auto factory = reinterpret_cast<std::shared_ptr<Type> (*)(Dependencies...)>(factoryRecipe->getFactory());
811 
812  InstanceGetter<std::shared_ptr<Type>, Dependencies...> getter = [factory](Dependencies... dependencies) {
813  return factory(std::move(dependencies)...);
814  };
815 
816  auto temp = std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, getter));
817  return new std::shared_ptr<void>(temp);
818 }
819 
820 template <typename Type, typename Annotation, typename... Dependencies>
821 inline void* CookBook::produceFromAnnotatedWeakFactoryRecipe(
822  std::shared_ptr<AbstractRecipe> recipe,
823  RuntimeManufactory& runtimeManufactory,
824  void* cachedInstance) {
825  if (cachedInstance) {
826  return cachedInstance;
827  }
828 
829  auto factoryRecipe = reinterpret_cast<FactoryRecipe*>(recipe.get());
830  auto factory = reinterpret_cast<Annotated<Annotation, Type> (*)(Dependencies...)>(factoryRecipe->getFactory());
831 
832  InstanceGetter<std::shared_ptr<Type>, Dependencies...> getter = [factory](Dependencies... dependencies) {
833  return factory(std::move(dependencies)...);
834  };
835 
836  auto temp = std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, getter));
837  return new std::shared_ptr<void>(temp);
838 }
839 
840 template <typename Type, typename... Dependencies>
841 inline void* CookBook::produceFromWeakFunctionRecipe(
842  std::shared_ptr<AbstractRecipe> recipe,
843  RuntimeManufactory& runtimeManufactory,
844  void* cachedInstance) {
845  if (cachedInstance) {
846  return cachedInstance;
847  }
848  auto functionRecipe = reinterpret_cast<FunctionRecipe*>(recipe.get());
849  auto function = *static_cast<std::function<std::shared_ptr<Type>(Dependencies...)>*>(functionRecipe->getFunction());
850 
851  auto temp = std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, function));
852  return new std::shared_ptr<void>(temp);
853 }
854 
855 template <typename Type, typename Annotation, typename... Dependencies>
856 inline void* CookBook::produceFromAnnotatedWeakFunctionRecipe(
857  std::shared_ptr<AbstractRecipe> recipe,
858  RuntimeManufactory& runtimeManufactory,
859  void* cachedInstance) {
860  if (cachedInstance) {
861  return cachedInstance;
862  }
863  auto functionRecipe = reinterpret_cast<FunctionRecipe*>(recipe.get());
864  auto function =
865  *static_cast<std::function<Annotated<Annotation, Type>(Dependencies...)>*>(functionRecipe->getFunction());
866 
867  auto temp = std::shared_ptr<Type>(invokeWithDependencies(runtimeManufactory, function));
868  return new std::shared_ptr<void>(temp);
869 }
870 
871 template <typename Type>
872 inline void CookBook::deleteFunctionForSharedRecipe(void* cachedInstance) {
873  auto objectToDelete = static_cast<std::shared_ptr<Type>*>(cachedInstance);
874  delete objectToDelete;
875 }
876 
877 template <typename Type, typename... Dependencies>
878 inline void CookBook::deleteFunctionForFunctionRecipeFunction(void* function) {
879  auto objectToDelete = static_cast<std::function<Type(Dependencies...)>*>(function);
880  delete objectToDelete;
881 }
882 
883 template <typename Type, typename... Dependencies>
884 inline void* CookBook::produceFromUniqueFactoryRecipe(
885  std::shared_ptr<AbstractRecipe> recipe,
886  RuntimeManufactory& runtimeManufactory,
887  void* cachedInstance) {
888  auto factoryRecipe = reinterpret_cast<FactoryRecipe*>(recipe.get());
889  auto factory = reinterpret_cast<std::unique_ptr<Type> (*)(Dependencies...)>(factoryRecipe->getFactory());
890 
891  InstanceGetter<std::unique_ptr<Type>, Dependencies...> getter = [factory](Dependencies... dependencies) {
892  return factory(std::move(dependencies)...);
893  };
894 
895  return new std::unique_ptr<Type>(invokeWithDependencies(runtimeManufactory, getter));
896 }
897 
898 template <typename Type, typename... Dependencies>
899 inline void* CookBook::produceFromUniqueFunctionRecipe(
900  std::shared_ptr<AbstractRecipe> recipe,
901  RuntimeManufactory& runtimeManufactory,
902  void* cachedInstance) {
903  auto functionRecipe = reinterpret_cast<FunctionRecipe*>(recipe.get());
904  auto function = *static_cast<std::function<std::unique_ptr<Type>(Dependencies...)>*>(functionRecipe->getFunction());
905 
906  return new std::unique_ptr<Type>(invokeWithDependencies(runtimeManufactory, function));
907 }
908 
910 
911 template <typename Type>
912 inline bool CookBook::GetWrapperCollection::append(GetWrapper getWrapper) {
913  auto typeIndex = avsCommon::utils::getTypeIndex<Type>();
914 
915  if (m_types.end() == m_types.find(typeIndex)) {
916  m_orderedGetWrappers.push_back(getWrapper);
917  m_types.insert({typeIndex, m_orderedGetWrappers.size() - 1});
918 
919  return true;
920  }
921 
922  return false;
923 }
924 
925 } // namespace internal
926 } // namespace acsdkManufactory
927 } // namespace alexaClientSDK
928 
929 #endif // ACSDKMANUFACTORY_INTERNAL_COOKBOOK_IMP_H_
bool doRequiredGets(RuntimeManufactory &runtimeManufactory)
Definition: CookBook_imp.h:612
CookBook & addPrimaryFactory(std::function< std::shared_ptr< Type >(Dependencies...)> factory)
Definition: CookBook_imp.h:93
CookBook & addRetainedFactory(std::function< std::shared_ptr< Type >(Dependencies...)> factory)
Definition: CookBook_imp.h:325
::std::string string
Definition: gtest-port.h:1097
bool checkCompleteness()
Definition: CookBook_imp.h:700
Type get()
Definition: RuntimeManufactory_imp.h:34
CookBook & addUnloadableFactory(std::function< std::shared_ptr< Type >(Dependencies...)> factory)
Definition: CookBook_imp.h:429
CookBook & addUniqueFactory(std::function< std::unique_ptr< Type >(Dependencies...)> factory)
Definition: CookBook_imp.h:41
CookBook & addCookBook(const CookBook &cookBook)
Definition: CookBook_imp.h:582
typename RemoveCvref< Type >::type RemoveCvref_t
Definition: TypeTraitsHelper.h:40
std::unique_ptr< Type > createUniquePointer(RuntimeManufactory &runtimeManufactory)
Definition: CookBook_imp.h:630
Whether or not curl logs should be emitted.
Definition: AVSConnectionManager.h:36
std::unique_ptr< AbstractPointerCache > createPointerCache()
Definition: CookBook_imp.h:670
type
Definition: upload.py:443
CookBook & addRequiredFactory(std::function< std::shared_ptr< Type >(Dependencies...)> factory)
Definition: CookBook_imp.h:209
void acsdkError(const LogEntry &entry)
CookBook & addInstance(const Type &instance)
Definition: CookBook_imp.h:533
const T & move(const T &t)
Definition: gtest-port.h:1317
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