[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / utils / ComponentContainer.h
blob3aa826a82d9a498862564c954d13d72d677b11e4
1 /*
2 * Copyright (C) 2022 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #pragma once
11 #include "threads/CriticalSection.h"
13 #include <cstddef>
14 #include <memory>
15 #include <mutex>
16 #include <stdexcept>
17 #include <typeindex>
18 #include <unordered_map>
19 #include <utility>
21 //! \brief A generic container for components.
22 //! \details A component has to be derived from the BaseType.
23 //! Only a single instance of each derived type can be registered.
24 //! Intended use is through inheritance.
25 template<class BaseType>
26 class CComponentContainer
28 public:
29 //! \brief Obtain a component.
30 template<class T>
31 std::shared_ptr<T> GetComponent()
33 return std::const_pointer_cast<T>(std::as_const(*this).template GetComponent<T>());
36 //! \brief Obtain a component.
37 template<class T>
38 std::shared_ptr<const T> GetComponent() const
40 std::unique_lock<CCriticalSection> lock(m_critSection);
41 const auto it = m_components.find(std::type_index(typeid(T)));
42 if (it != m_components.end())
43 return std::static_pointer_cast<const T>((*it).second);
45 throw std::logic_error("ComponentContainer: Attempt to obtain non-existent component");
48 //! \brief Returns number of registered components.
49 std::size_t size() const { return m_components.size(); }
51 protected:
52 //! \brief Register a new component instance.
53 void RegisterComponent(const std::shared_ptr<BaseType>& component)
55 if (!component)
56 return;
58 // Note: Extra var needed to avoid clang warning
59 // "Expression with side effects will be evaluated despite being used as an operand to 'typeid'"
60 // https://stackoverflow.com/questions/46494928/clang-warning-on-expression-side-effects
61 const auto& componentRef = *component;
63 std::unique_lock<CCriticalSection> lock(m_critSection);
64 m_components.insert({std::type_index(typeid(componentRef)), component});
67 //! \brief Deregister a component.
68 void DeregisterComponent(const std::type_info& typeInfo)
70 std::unique_lock<CCriticalSection> lock(m_critSection);
71 m_components.erase(typeInfo);
74 private:
75 mutable CCriticalSection m_critSection; //!< Critical section for map updates
76 std::unordered_map<std::type_index, std::shared_ptr<BaseType>>
77 m_components; //!< Map of components