ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
lang/plugins.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_lang of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib::lang {
9
10//==================================================================================================
11/// This class usually is used as a base class for types that need to manage simple plug-ins.
12/// Within \alib itself, for example, classes #"Configuration" and
13/// #"Compiler" inherit from this class.
14///
15/// Plug-ins are organized with a prioritization. This means, that plug-ins which are inserted with
16/// a higher priority are 'asked' first, and those with a lower value become 'asked' only if higher
17/// prioritized plug-ins did not answer.<br>
18/// However, a derived class can deviate from this behavior. Using the typical \alib class design,
19/// all internal fields are \c protected, hence freely accessible by derived classes.
20///
21/// @tparam TPlugin The plug-in type that this class manages. This type is publicly exposed as
22/// #".PluginType"
23/// This type is publicly exposed as #".PrioritiesType".
24//==================================================================================================
25template<typename TPlugin, typename TPriorities>
26class Plugin {
27 public:
28 /// This exposes the template parameter \p{TPlugin} to the outer world.
29 using PluginType= TPlugin;
30
31 /// This exposes the template parameter \p{pTPlugin} to the outer world.
32 using PrioritiesType= TPriorities;
33
34 protected:
35 /// The priority of this plug-in.
37
38 /// Constructor which is protected, as this is a bace class.
39 /// @param pPriority The priority that this plug-in uses.
41 : priority (pPriority) {}
42
43 public:
44 /// Returns the priority of this plug-in which is set during construction.
45 /// @return The priority of this plugin.
47
48}; //class Plugin
49
50//==================================================================================================
51/// This class usually is used as a base class for types that need to manage simple plug-ins.
52/// Within \alib itself, for example, classes #"Configuration" and
53/// #"Compiler" inherit from this class.
54///
55/// Plug-ins are organized with a prioritization. This means, that plug-ins which are inserted with
56/// a higher priority are 'asked' first, and those with a lower value become 'asked' only if higher
57/// prioritized plug-ins did not answer.<br>
58/// However, a derived class can deviate from this behavior. Using the typical \alib class design,
59/// all internal fields are \c protected, hence freely accessible by derived classes.
60///
61/// @tparam TPlugin The type of the plug-ins managed. This type is publicly exposed as
62/// #".PluginType".
63/// @tparam TPriorities The enumeration type providing the default "plug-in slots" and priorities
64/// of the plug-ins managed. This type is publicly exposed as #".PrioritiesType".
65//==================================================================================================
66template<typename TPlugin, typename TPriorities>
68 //################################################################################################
69 // public fields and types
70 //################################################################################################
71 public:
72 /// This exposes the template parameter \p{pTPlugin} to the outer world.
73 using PluginType= TPlugin;
74
75 /// This exposes the template parameter \p{pTPlugin} to the outer world.
76 using PrioritiesType= TPriorities;
77
78 /// Type definition for elements of the list of plug-ins with their priority.
79 struct Slot {
80 TPlugin* plugin; ///< The plug-in.
81 bool owned; ///< If \c true, this container is responsible for deleting
82 ///< the plug-in object.
83 };
84
85 /// The list that stores the plugins.
86 using PluginList= std::vector<Slot>;
87
88 //################################################################################################
89 // internal fields
90 //################################################################################################
91 protected:
92
93 /// The plug-ins we have attached in descending priority order.
95
96 //################################################################################################
97 // Constructor/destructor
98 //################################################################################################
99 public:
100 /// Destructor. All plug-ins that were inserted with parameter \p{responsibility} set to
101 /// #"Responsibility::Transfer;*" will be deleted.
103 for( auto& slot : plugins )
104 if( slot.owned )
105 delete slot.plugin;
106 }
107
108
109
110 //################################################################################################
111 // interface
112 //################################################################################################
113 public:
114 /// Adds the given plug-in to the list of plug-ins.
115 ///
116 /// @param plugin The plug-in to insert.
117 /// @param responsibility If \c Responsibility::Transfer, the given plugin will be deleted
118 /// with destruction of this object.
119 /// Defaults to \c Responsibility::KeepWithSender which denotes that
120 /// the life-cycle of the given external buffer is managed elsewhere.
121 void InsertPlugin( TPlugin* plugin, lang::Responsibility responsibility
123 ALIB_ASSERT_ERROR( plugin != nullptr, "FSPLUGINS", "Nullptr provided for plugin." )
124
125 ALIB_STATIC_ASSERT( Plugin_type_not_virtual,
126 std::has_virtual_destructor<TPlugin>::value
127 || responsibility == lang::Responsibility::KeepWithSender,
128 "Can't take responsibility for plug-in destruction. TPlugin has no virtual destructor.")
129
130 // gcc needs this captured, clang warns.
131 // Its about the ALIB_CALLER inside ALIB_ASSERT_ERROR
133 plugins.insert( std::find_if( plugins.begin(), plugins.end(),
134 [plugin,this]( Slot& ppp)
135 {
136 ALIB_ASSERT_ERROR( ppp.plugin->GetPriority() != plugin->GetPriority(), "FSPLUGINS",
137 "PluginContainer::InsertPlugin(): Plug-in with same priority {} exists",
138 ppp.plugin->GetPriority() )
139
140 return ppp.plugin->GetPriority() < plugin->GetPriority();
141 } ),
142 Slot { plugin, responsibility == lang::Responsibility::Transfer } );
144 }
145
146
147 /// Removes the given plug-in from the list of plug-ins.
148 ///
149 /// Responsibility for deletion of removed plug-ins is passed to the remover in case the
150 /// plug-in was inserted with parameter \p{responsibility} set to
151 /// #"Responsibility::Transfer;*".
152 ///
153 /// @param plugIn The plug-in to be removed.
154 /// @return \c true if the plug-in was removed, else \c false, which indicates that the
155 /// given plug-in was not found.
156 bool RemovePlugin( TPlugin* plugIn ) {
157 auto it= std::find_if( plugins.begin(), plugins.end(), [plugIn](Slot& pair)
158 {
159 return pair.plugin == plugIn;
160 } );
161 if( it != plugins.end() ) {
162 plugins.erase( it );
163 return true;
164 }
165
166 ALIB_WARNING("LANG", "PluginContainer::RemovePlugin(): Plug-in not found for removal.")
167 return false;
168 }
169
170 /// Remove the plug-in at the given \p{idx} from the list of plug-ins.
171 ///
172 /// Responsibility for deletion of removed plug-ins is passed to the remover in case the
173 /// plug-in was inserted with parameter \p{responsibility} set to
174 /// #"Responsibility::Transfer;*".
175 ///
176 /// @param idx The index of the plug-in to remove.
177 void RemovePlugin( integer idx ) {
178 ALIB_ASSERT_WARNING( idx < CountPlugins(), "FSPLUGINS",
179 "PluginContainer::RemovePlugin(): Index out of bounds: {} >= {}", idx, CountPlugins() )
180 plugins.erase( plugins.begin() + idx );
181 }
182
183
184 /// Remove the plug-in with the given priority.
185 ///
186 /// Responsibility for deletion of removed plug-ins is passed to the remover in case the
187 /// plug-in was inserted with parameter \p{responsibility} set to
188 /// #"Responsibility::Transfer;*".
189 ///
190 /// @param priority The priority of the plug-in to remove.
191 /// @return \c true if the plug-in was removed, else \c false, which indicates that no
192 /// plug-in with the given priority was found.
193 TPlugin* RemovePlugin( TPriorities priority ) {
194 TPlugin* plugin= nullptr;
195 plugins.erase( std::remove_if( plugins.begin(), plugins.end(),
196 [priority, &plugin](Slot& entry)
197 {
198 if( entry.priority == priority) {
199 plugin= entry.plugin;
200 return true;
201 }
202 return false;
203 } ),
204 plugins.end() );
205
206 ALIB_ASSERT_WARNING( plugin, "FSPLUGINS", "No Plug-in was removed." )
207
208 return plugin;
209 }
210
211
212 /// Checks if any plug-in is attached. This is useful if optional configuration objects
213 /// are used. In case no plug-in was attached (by a third party), the effort to declare and
214 /// search a variable can be omitted.
215 /// @return \c true if this object has any plugin set, \c false otherwise.
216 bool HasPlugins() { return CountPlugins() > 0; }
217
218 /// Returns the number of plug-ins attached.
219 /// @return The quantity of attached plug-ins.
220 integer CountPlugins() { return integer(plugins.size()); }
221
222 /// Returns the plug-in with the given internal number. Valid numbers are
223 /// <c>0..[#".CountPlugins"]</c>. No internal checks for valid plug-in numbers are made.
224 ///
225 /// @param number The number of the plug-in requested.
226 /// @return The plug-in requested.
227 TPlugin* GetPlugin( integer number ) { return plugins[size_t(number)].plugin; }
228
229 /// Returns the priority of the plug-in with the given internal number. Valid numbers are
230 /// 0..[#".CountPlugins"]. No internal checks for valid plug-in numbers are made.
231 ///
232 /// @param number The number of the plug-in requested.
233 /// @return The priortiy of the plug-in.
234 TPriorities GetPriority( integer number ) { return plugins[size_t(number)].priority; }
235
236
237 /// Returns the plug-in with the given priority. If the plug-in does not exist, \c nullptr
238 /// is returned.
239 ///
240 /// @param priority The priority of the plug-in to return.
241 /// @return The plug-in requested or \c nullptr if not available.
242 TPlugin* GetPlugin( TPriorities priority ) {
243 auto it = std::find_if( plugins.begin(), plugins.end(),
244 [priority](Slot& pair) { return pair.priority == priority; } );
245 if( it != plugins.end() )
246 return it->plugin;
247 return nullptr;
248 }
249
250 /// Same as #".GetPlugin(integer)", but converts the plug-in found to the template type, which
251 /// has to be explicitly provided with the invocation of this method.
252 ///
253 /// A type-check is performed using standard C++ \c dynamic_cast mechanics.
254 /// If the plugin has a different type, \c nullptr is returned.
255 ///
256 /// @tparam TPluginType The type of the plugin to search.
257 /// @param priority The priority of the plug-in to return.
258 /// @return The plug-in of requested type and priority. \c nullptr if not available.
259 template<typename TPluginType>
260 TPluginType* GetPluginTypeSafe( TPriorities priority )
261 { return dynamic_cast<TPluginType*>( GetPlugin( priority ) ); }
262
263 /// Searches the list of plug-ins for the first found with type \p{TPluginType}.
264 ///
265 /// @tparam TPluginType The type of the plugin to search.
266 /// @return The plug-in of requested type. \c nullptr if not available.
267 template<typename TPluginType>
268 TPluginType* GetPluginTypeSafe() {
269 TPluginType* cast= nullptr;
270 for( auto& ppp : plugins )
271 if( (cast= dynamic_cast<TPluginType*>( ppp.plugin )) != nullptr )
272 break;
273
274 return cast;
275 }
276
277}; // class PluginContainer
278
279} // namespace [alib::lang]
#define ALIB_WARNING(domain,...)
#define ALIB_STATIC_ASSERT(CondVariable, Cond, Message)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_POP_ALLOWANCE
#define ALIB_EXPORT
#define ALIB_ALLOW_UNUSED_LAMBDA_CAPTURE
#define ALIB_ASSERT_ERROR(cond, domain,...)
TPlugin * GetPlugin(TPriorities priority)
TPlugin * RemovePlugin(TPriorities priority)
TPlugin PluginType
This exposes the template parameter pTPlugin to the outer world.
void RemovePlugin(integer idx)
std::vector< Slot > PluginList
The list that stores the plugins.
TPriorities GetPriority(integer number)
bool RemovePlugin(TPlugin *plugIn)
TPlugin * GetPlugin(integer number)
TPriorities PrioritiesType
This exposes the template parameter pTPlugin to the outer world.
PluginList plugins
The plug-ins we have attached in descending priority order.
void InsertPlugin(TPlugin *plugin, lang::Responsibility responsibility=lang::Responsibility::KeepWithSender)
TPluginType * GetPluginTypeSafe(TPriorities priority)
TPluginType * GetPluginTypeSafe()
TPriorities PrioritiesType
This exposes the template parameter pTPlugin to the outer world.
TPlugin PluginType
This exposes the template parameter TPlugin to the outer world.
PrioritiesType priority
The priority of this plug-in.
PrioritiesType GetPriority() const
Plugin(PrioritiesType pPriority)
platform_specific integer
Definition integers.hpp:32
@ KeepWithSender
Keeps responsibility, e.g., when passing an object.
Type definition for elements of the list of plug-ins with their priority.