RTC Toolkit 5.0.0
Loading...
Searching...
No Matches
factoryRegistry.ipp
Go to the documentation of this file.
1
13// Note this is a template implementation file and should not be included directly.
14// The typical header protection macro is not added to avoid it showing up in Doxygen API
15// documentation.
16#pragma once
17
18#include <algorithm>
19#include <cassert>
20
22
23template <class BaseIf>
25 // Check that all factories are unregistered at the time we are destroying this factory registry
26 // object. If this is not the case, then either a library is incorrectly implemented and not
27 // cleaning up properly, or the registry is being destroyed before all shared libraries got a
28 // chance to cleanup and deregister their factories. In either case, this is a bug, which this
29 // assertion failure exposes.
30#ifndef NDEBUG
31 std::scoped_lock lock(m_mutex);
32 assert(m_factories.size() == 0);
33#endif
34}
35
36template <class BaseIf>
38 // Note that we should not log in this function, since it will likely be called during process
39 // startup when no logging facilities are configured or appropriate.
40 std::scoped_lock lock(m_mutex);
41 auto position = std::find(m_factories.begin(), m_factories.end(), factory);
42 if (position == m_factories.end()) {
43 m_factories.push_back(factory);
44 }
45}
46
47template <class BaseIf>
49 // Note that similar logging restriction applies to this method as for Register, but during
50 // process termination.
51 std::scoped_lock lock(m_mutex);
52 auto position = std::find(m_factories.begin(), m_factories.end(), factory);
53 if (position != m_factories.end()) {
54 m_factories.erase(position);
55 }
56}
57
58template <class BaseIf>
61 std::scoped_lock lock(m_mutex);
62 auto factory = std::find_if(
63 m_factories.begin(), m_factories.end(), [&](auto& x) { return x->CanHandle(id); });
64 if (factory != m_factories.end()) {
65 return *factory;
66 } else {
67 return nullptr;
68 }
69}
70
71template <class BaseIf>
72std::shared_ptr<FactoryRegistry<BaseIf>> FactoryRegistry<BaseIf>::GetInstance() {
73 // Using a static local shared pointer to the global instance, since the C++ language guarantees
74 // will defer the initialisation of an empty registry object to the very first call of
75 // GetInstance. And this is done in a thread-safe manner. In addition, on the Linux platform at
76 // least, the linker will ensure there is only one copy of this object, even if the symbol was
77 // compiled into multiple translation units.
78 // The advantage of the static local variable versus a static class attribute is that this
79 // approach is more generic. Whenever a new type for T is used by the end user of this class,
80 // there is nothing special that needs to be done by the user. While using a static class
81 // attribute, e.g. s_registry, would require adding additional template specialisations to the
82 // common shared library of the following form:
83 //
84 // template<>
85 // std::shared_ptr<FactoryRegistry<MyInterface>> FactoryRegistry<MyInterface>::s_registry {};
86 //
87 // This would limit how flexible the FactoryRegistry class is.
88 //
89 // The reason to use a shared_ptr is to use reference counting to control the life-cycle of the
90 // registry object. The RegisterFactory must hold a shared pointer to the factory registry
91 // object for as long as the RegisterFactory exists, i.e. for as long as it has registered a
92 // factory with the registry. Using shared pointers should guarantee that the registry object
93 // will only be deleted once all relevant RegisterFactory classes are cleaned up.
94 // Experience has shown that if we do not use a shared_ptr and simply return a reference to a
95 // local object, the cleanup order becomes dependent on the link order of the shared libraries,
96 // i.e. undefined.
97 //
98 static std::shared_ptr<FactoryRegistry<BaseIf>> registry =
99 std::make_shared<FactoryRegistry<BaseIf>>();
100 return registry;
101}
102
103template <class BaseIf, class Factory>
105 : m_registry(FactoryRegistry<BaseIf>::GetInstance()) {
106 m_registry->Register(&m_factory);
107}
108
109template <class BaseIf, class Factory>
111 m_registry->Deregister(&m_factory);
112}
113
114} // namespace rtctk::componentFramework
The base class for all factory objects that are registered in the FactoryRegistry.
Definition factoryRegistry.hpp:57
A simple registry of various factory objects.
Definition factoryRegistry.hpp:47
void Register(const FactoryIf *factory)
Register the factory if it was not already registered.
Definition factoryRegistry.ipp:37
void Deregister(const FactoryIf *factory) noexcept
Remove the factory from the registry if it was already registered.
Definition factoryRegistry.ipp:48
~FactoryRegistry()
Definition factoryRegistry.ipp:24
static std::shared_ptr< FactoryRegistry< BaseIf > > GetInstance()
Returns the registry singleton.
Definition factoryRegistry.ipp:72
const FactoryIf * FindCompatibleFactory(const AdapterIdType &id) const noexcept
Finds the first factory that can handle the given identifier.
Definition factoryRegistry.ipp:60
typename BaseIf::AdapterIdType AdapterIdType
Definition factoryRegistry.hpp:49
RegisterFactory()
Definition factoryRegistry.ipp:104
~RegisterFactory()
Definition factoryRegistry.ipp:110
Definition commandReplier.cpp:22
elt::mal::future< std::string > InjectReqRepEvent(StateMachineEngine &engine)
Definition malEventInjector.hpp:23